문제
https://www.acmicpc.net/problem/10711
10711: 모래성
명우와 친구들은 여름방학을 맞이하여 해변가에 놀러가기로 했다. 이번에 여행을 떠난 해수욕장의 이름은 ALPS(Awsome Land & Poor Sea)이다. 해변가에서 수영복을 입은 미녀들에게 관심이 많은 원철이와는 달리 명우는 해변가의 모래에 더 관심이 많다. 해변가의 모래는 무한한 것들을 만들 수 있는 가능성을 내포하고 있다. 또한 이렇게 만들어진 작품이 파도에 의해 사라지는 모습은, 마치 자신이 가장 빛날 수 있는 시간을 알고 스스로 아름답게 산화하려는 것으로 보인다. 이런 완벽에 가까운 물품인 모래를 두고서 해수욕이나 헤엄을 치는 것은 인생을 낭비하는 것과 같다고 생각한다. 하지만 아무도 명우의 말에 공감해주지 못했고, 결국 명우는 혼자서 모래성을 만들었다.
www.acmicpc.net
해설
- 2개의 2차원 배열을 사용한다.
- 맵 배열 .은 0으로 나머지 수는 그대로 사용하여 맵을 만들어낸다.
- 나머지는 해당 맵의 x,y에 몇개의 파도 (0)이 존재하는지를 저장한다.
- 모든 파도(0)에 대하여 BFS를 수행한다.
- 이는 현재 파도인 경우만 탐색한다. (이번 탐색의 파도에 의해 무너진 모래성을 0으로 보면 안된다.)
- 만약, 탐색 도중 파도에 의해 무너진 모래성의 일부가 있다면 이를 다음 탐색의 nextQueue에 넣어둔다.
- 모든 파도에 대해 수행하면 ++count[nx][ny]를 통해 해당 위치에 8방향에 파도가 몇개 있는지가 갱신된다.
- 이때, 새롭게 모래성 -> 파도로 변한 것만을 nextQueue에 넣었고,
(모든 파도에 대해서 다시 탐색 X, 새롭게 파도가 된 것만 확인)
count[][]는 초기화되지 않았으므로 다시 전체를 탐색하지 않아도 된다. (시간 최적화 포인트) - 이렇게 수행하다보면 모래성이 더 이상 파도로 변하지 않는 순간이 온다. (이는, nextQueue에 원소가 하나도 없는 것)
- 이때의 time을 출력한다.
코드 (BFS, 시뮬레이션)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.StringTokenizer;
public class BOJ10711 {
static int[][] map;
static int[][] count;
static Queue<Pair> queue = new ArrayDeque<Pair>();
static int N, M;
static int[] dx = {-1, -1, -1, 0, 0, 1, 1, 1};
static int[] dy = {-1, 0, 1, -1, 1, -1, 0, 1};
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());
map = new int[N][M];
count = new int[N][M];
for (int i = 0; i < N; i++) {
String input = br.readLine();
for (int j = 0; j < M; j++) {
char c = input.charAt(j);
if (c == '.') {
map[i][j] = 0;
queue.offer(new Pair(i, j));
} else {
map[i][j] = c - '0';
}
}
}
int time = 0;
while (true) {
if(simulation()) break;
time++;
}
System.out.println(time);
}
private static boolean simulation() {
Queue<Pair> nextQueue = new ArrayDeque<>();
while (!queue.isEmpty()) {
Pair p = queue.poll();
for (int i = 0; i < 8; i++) {
int nx = p.x + dx[i];
int ny = p.y + dy[i];
if (nx < 0 || ny < 0 || nx >= N || ny >= M || map[nx][ny] == 0) continue;
if (++count[nx][ny] == map[nx][ny]) {
map[nx][ny] = 0;
nextQueue.offer(new Pair(nx, ny));
}
}
}
if(nextQueue.isEmpty()) return true;
queue = nextQueue;
return false;
}
}
class Pair{
int x, y;
public Pair(int x, int y) {
this.x = x;
this.y = y;
}
}
결론
치즈와 마찬가지로 모래성이 아닌 바깥부터 탐색을 시작하고,
변경된 부분만을 다시 큐에 넣어서 탐색하는 것이 시간 효율성을 높이는 것이 포인트이다.
'CodingTest > 백준' 카테고리의 다른 글
[백준] BOJ 2531 회전 초밥 (실버 1) (0) | 2024.06.20 |
---|---|
[백준] BOJ 22255 호석사우르스 (골드 2) (2) | 2024.06.19 |
[백준] BOJ 1661 다솜이의 신발가게 (골드 2) (0) | 2024.06.19 |
[백준] BOJ 3980 선발 명단 (골드 5) (0) | 2024.06.19 |
[백준] BOJ 17208 카우버거 알바생 (골드 4) (0) | 2024.06.19 |