Algorithm/BOJ
BAEK21610. 마법사 상어와 비바라기
윤프라이즈
2023. 5. 12. 21:01
2023년 5월 10일
https://www.acmicpc.net/problem/21610
시간 : ❤❤❤🤍🤍
만족도 : ❤❤❤🤍🤍
- 8방향 델타 탐색
- 처음에 코드를 작성했을 때 5번 과정에서 3중 반복문으로 인해 시간 초과가 났었다..
- 어느 부분에서 시간 초과가 발생했는지 원인을 찾는데 시간이 오래걸렸다..
코드
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Arrays; import java.util.LinkedList; import java.util.Queue; import java.util.StringTokenizer; public class Main { static int N,M,d,s; static int[][] graph; // ←, ↖, ↑, ↗, →, ↘, ↓, ↙ static int[] dx = {0, -1, -1, -1, 0, 1, 1, 1}; static int[] dy = {-1, -1, 0, 1, 1, 1, 0, -1}; static int[] dgx = {-1, -1, 1, 1}; static int[] dgy = {-1, 1, -1, 1}; static int[] start; static boolean[][] visit; static Queue<int[]> cloud = new LinkedList<>(); public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); N = Integer.parseInt(st.nextToken()); M = Integer.parseInt(st.nextToken()); graph = new int[N][N]; for (int i = 0; i < N; i++) { st = new StringTokenizer(br.readLine()); for (int j = 0; j < N; j++) { graph[i][j] = Integer.parseInt(st.nextToken()); } } // 처음 구름의 위치 큐에 삽입. cloud.add(new int[] {N-2, 0}); cloud.add(new int[] {N-2, 1}); cloud.add(new int[] {N-1, 0}); cloud.add(new int[] {N-1, 1});
for (int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
d = Integer.parseInt(st.nextToken());
s = Integer.parseInt(st.nextToken());
// 1. 모든 구름이 d방향으로 s칸 이동한다.
int size = cloud.size();
for (int k = 0; k < size; k++) {
int[] coord = cloud.poll();
int x = coord[0];
int y = coord[1];
int[] next = move(x, y);
cloud.add(next);
}
// 2. 각 구름에서 비가 내려 구름이 있는 칸의 바구니에 저장된 물의 양이 1 증가한다.
for (int k = 0; k < size; k++) {
int[] coord = cloud.poll();
int x = coord[0];
int y = coord[1];
graph[x][y]++;
int[] next = new int[] {x, y};
cloud.add(next);
}
// 3. 구름이 모두 사라진다.
// 4. 물복사버그 마법을 시전
for (int k = 0; k < size; k++) {
int[] coord = cloud.poll();
int x = coord[0];
int y = coord[1];
int backet = 0;
for (int j = 0; j < 4; j++) {
int nnx = x + dgx[j];
int nny = y + dgy[j];
if (nnx < 0 || nny < 0 || nnx >= N || nny >= N) continue;
if (graph[nnx][nny] > 0) backet++;
}
graph[x][y] += backet;
cloud.add(new int[] {x, y});
}
// 5.
visit = new boolean[N][N];
while(!cloud.isEmpty()) {
int[] cur = cloud.poll();
visit[cur[0]][cur[1]] = true;
}
for (int p = 0; p < N; p++) {
for (int q = 0; q < N; q++) {
if (!visit[p][q] && graph[p][q] >= 2) {
graph[p][q] -= 2;
cloud.add(new int[] {p,q});
}
int ans = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
ans += graph[i][j];
}
}
System.out.println(ans);
}
// 구름 이동
public static int[] move(int x, int y) {
int movetoX = dx[d-1];
int movetoY = dy[d-1];
int nx = x + movetoX * s;
int ny = y + movetoY * s;
if (nx >= N) {
nx = nx % N;
} else if (nx < 0) {
int temp = Math.abs(nx);
temp = temp % N;
nx = N - temp;
if (nx == N) nx = 0;
}
if (ny >= N) {
ny = ny % N;
} else if (ny < 0) {
int temp = Math.abs(ny);
temp = temp % N;
ny = N - temp;
if (ny == N) ny = 0;
}
int[] moved = new int[] {nx, ny};
return moved;
}
}
```
시간 초과 났었던 코드
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Arrays; import java.util.LinkedList; import java.util.Queue; import java.util.StringTokenizer; public class Main { static int N,M,d,s; static int[][] graph; // ←, ↖, ↑, ↗, →, ↘, ↓, ↙ static int[] dx = {0, -1, -1, -1, 0, 1, 1, 1}; static int[] dy = {-1, -1, 0, 1, 1, 1, 0, -1}; static int[] cx = {0, 0, 1, 1}; static int[] cy = {0, 1, 0, 1}; static int[] dgx = {-1, -1, 1, 1}; static int[] dgy = {-1, 1, -1, 1}; static int[] start; static Queue<int[]> cloud = new LinkedList<>(); static Queue<int[]> temp = new LinkedList<>(); public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); N = Integer.parseInt(st.nextToken()); M = Integer.parseInt(st.nextToken()); graph = new int[N][N]; for (int i = 0; i < N; i++) { st = new StringTokenizer(br.readLine()); for (int j = 0; j < N; j++) { graph[i][j] = Integer.parseInt(st.nextToken()); } } cloud.add(new int[] {N-2, 0}); cloud.add(new int[] {N-2, 1}); cloud.add(new int[] {N-1, 0}); cloud.add(new int[] {N-1, 1});
for (int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
d = Integer.parseInt(st.nextToken());
s = Integer.parseInt(st.nextToken());
// 1. 모든 구름이 d방향으로 s칸 이동한다.
int size = cloud.size();
for (int k = 0; k < size; k++) {
int[] coord = cloud.poll();
int x = coord[0];
int y = coord[1];
int[] next = move(x, y);
cloud.add(next);
}
// 2. 각 구름에서 비가 내려 구름이 있는 칸의 바구니에 저장된 물의 양이 1 증가한다.
for (int k = 0; k < size; k++) {
int[] coord = cloud.poll();
int x = coord[0];
int y = coord[1];
graph[x][y]++;
int[] next = new int[] {x, y};
cloud.add(next);
}
// 3. 구름이 모두 사라진다.
// 4. 물복사버그 마법을 시전
for (int k = 0; k < size; k++) {
int[] coord = cloud.poll();
int x = coord[0];
int y = coord[1];
int backet = 0;
for (int j = 0; j < 4; j++) {
int nnx = x + dgx[j];
int nny = y + dgy[j];
if (nnx < 0 || nny < 0 || nnx >= N || nny >= N) continue;
if (graph[nnx][nny] > 0) backet++;
}
graph[x][y] += backet;
cloud.add(new int[] {x, y});
}
// 5.
for (int p = 0; p < N; p++) {
for (int q = 0; q < N; q++) {
boolean flag = false;
for (int e = 0; e < size; e++) {
int[] cur = cloud.poll();
if (p == cur[0] && q == cur[1]) flag = true;
cloud.add(cur);
}
if (!flag) {
if (graph[p][q] >= 2) {
temp.add(new int[] {p,q});
graph[p][q] -= 2;
}
}
}
}
while(!cloud.isEmpty()) cloud.poll();
while(!temp.isEmpty()) cloud.add(temp.poll());
}
int ans = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
ans += graph[i][j];
}
}
System.out.println(ans);
}
// 구름 이동
public static int[] move(int x, int y) {
int movetoX = dx[d-1];
int movetoY = dy[d-1];
int nx = x + movetoX * s;
int ny = y + movetoY * s;
if (nx >= N) {
nx = nx % N;
} else if (nx < 0) {
int temp = Math.abs(nx);
temp = temp % N;
nx = N - temp;
if (nx == N) nx = 0;
}
if (ny >= N) {
ny = ny % N;
} else if (ny < 0) {
int temp = Math.abs(ny);
temp = temp % N;
ny = N - temp;
if (ny == N) ny = 0;
}
int[] moved = new int[] {nx, ny};
return moved;
}
}
```