Skip to content

Commit 17a8a07

Browse files
committed
백제완: [CT] 나무 타이쿤_240927
1 parent 0ffcf59 commit 17a8a07

File tree

1 file changed

+115
-0
lines changed

1 file changed

+115
-0
lines changed
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import java.io.BufferedReader;
2+
import java.io.InputStreamReader;
3+
import java.util.ArrayDeque;
4+
import java.util.Deque;
5+
import java.util.StringTokenizer;
6+
7+
public class Main {
8+
9+
static int n;
10+
static int[][] board; // 격자 칸
11+
static int[][] opers; // 각 년도의 이동 규칙
12+
static boolean[][] supple; // 영양제가 있는 위치
13+
14+
// 대각선 움직임 구현
15+
static int[] dy = { 0, 0, -1, -1, -1, 0, 1, 1, 1 };
16+
static int[] dx = { 0, 1, 1, 0, -1, -1, -1, 0, 1 };
17+
18+
public static void main(String[] args) throws Exception {
19+
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
20+
StringTokenizer st = new StringTokenizer(br.readLine());
21+
n = Integer.parseInt(st.nextToken());
22+
int m = Integer.parseInt(st.nextToken());
23+
board = new int[n][n];
24+
supple = new boolean[n][n];
25+
for (int i = 0; i < n; i++) {
26+
st = new StringTokenizer(br.readLine());
27+
for (int j = 0; j < n; j++)
28+
board[i][j] = Integer.parseInt(st.nextToken());
29+
}
30+
opers = new int[m][2]; // { 방향, 크기 }
31+
for (int i = 0; i < m; i++) {
32+
st = new StringTokenizer(br.readLine());
33+
opers[i][0] = Integer.parseInt(st.nextToken());
34+
opers[i][1] = Integer.parseInt(st.nextToken());
35+
}
36+
// 첫 영양제 위치
37+
supple[n - 2][0] = true;
38+
supple[n - 2][1] = true;
39+
supple[n - 1][0] = true;
40+
supple[n - 1][1] = true;
41+
// 년도만큼 반복
42+
for (int year = 0; year < m; year++) {
43+
move(year); // 영양제의 움직임 구현
44+
grow(); // 영양제 위치의 나무 성장
45+
cut(); // 크기가 2 이상인 나무를 잘라내고 영양제를 심음
46+
}
47+
// 남아있는 나무 높이들의 총 합
48+
int sum = 0;
49+
for (int i = 0; i < n; i++)
50+
for (int j = 0; j < n; j++)
51+
sum += board[i][j];
52+
System.out.println(sum);
53+
}
54+
55+
// 영양제의 움직임 구현
56+
private static void move(int year) {
57+
// 큐를 이용해 기존 영양제의 위치를 저장
58+
Deque<int[]> dq = new ArrayDeque<>();
59+
for (int i = 0; i < n; i++)
60+
for (int j = 0; j < n; j++)
61+
if (supple[i][j]) {
62+
supple[i][j] = false;
63+
dq.offer(new int[] { i, j });
64+
}
65+
// 년도에 따른 이동 방향 및 크기
66+
int[] oper = opers[year];
67+
while (!dq.isEmpty()) {
68+
int[] cur = dq.poll();
69+
// 영양제 위치 이동
70+
int y = (cur[0] + dy[oper[0]] * oper[1] + n) % n;
71+
int x = (cur[1] + dx[oper[0]] * oper[1] + n) % n;
72+
supple[y][x] = true; // 이동한 영양제 위치 표시
73+
board[y][x]++; // 영양제가 있는 위치의 나무 성장
74+
}
75+
}
76+
77+
// 영양제 위치의 나무 성장
78+
private static void grow() {
79+
for (int i = 0; i < n; i++)
80+
for (int j = 0; j < n; j++)
81+
// 영양제가 있다면
82+
if (supple[i][j]) {
83+
int cnt = 0;
84+
for (int k = 1; k <= 4; k++) {
85+
// 대각선 벡터값
86+
int y = i + dy[k * 2];
87+
int x = j + dx[k * 2];
88+
if (isValid(y, x) && board[y][x] > 0)
89+
cnt++;
90+
}
91+
// 대각선에 있는 나무의 수 만큼 성장
92+
board[i][j] += cnt;
93+
}
94+
}
95+
96+
// 크기가 2 이상인 나무를 잘라내고 영양제를 심음
97+
private static void cut() {
98+
for (int i = 0; i < n; i++)
99+
for (int j = 0; j < n; j++)
100+
// 영양제가 없었던 좌표에서 크기가 2 이상인 나무
101+
if (!supple[i][j]) {
102+
if (board[i][j] >= 2) {
103+
board[i][j] -= 2;
104+
supple[i][j] = true;
105+
}
106+
} else {
107+
// 기존에 있던 영양제는 없애줌
108+
supple[i][j] = false;
109+
}
110+
}
111+
112+
private static boolean isValid(int y, int x) {
113+
return 0 <= y && y < n && 0 <= x && x < n;
114+
}
115+
}

0 commit comments

Comments
 (0)