funmain() = with(Scanner(System.`in`)) { val (n, m) = Pair(nextInt(), nextInt()) val (dx, dy) = intArrayOf(1, 0, -1, 0) to intArrayOf(0, 1, 0, -1) // 상하좌우 네 방향을 의미 val paper = Array(n) { IntArray(m) } val visitMap = Array(n) { BooleanArray(m) } // 해당 칸을 방문했는지 여부를 저장 var max = 0// 그림의 최댓값 var num = 0// 그림의 개수
for (i in paper.indices) { for (j in paper[i].indices) { paper[i][j] = nextInt() } }
for (i in paper.indices) { for (j in paper[i].indices) { if (paper[i][j] == 0 || visitMap[i][j]) continue
val queue: Queue<Pair<Int, Int>> = LinkedList() var area = 0
num += 1 visitMap[i][j] = true queue.offer(i to j)
while (queue.isNotEmpty()) { area += 1
val cur = queue.poll()
for (dir in0 until 4) { // 상하좌우 칸을 탐색 val nx = cur.first + dx[dir] val ny = cur.second + dy[dir] // nx, ny에 dir에서 정한 방향의 인접한 칸의 좌표가 들어감
if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue// 범위 밖일 경우 넘어감 if (visitMap[nx][ny]|| paper[nx][ny] != 1) continue// 이미 방문한 칸이거나 색칠된 칸이 아닐 경우
visitMap[nx][ny] = true// (nx, ny)를 방문했다고 명시 queue.offer(nx to ny) } } max = max(max, area) } } println("$num\n$max") }
funmain() = with(Scanner(System.`in`)) { var date = 0 val (m, n) = nextInt() to nextInt() val (dx, dy) = intArrayOf(1, 0, -1, 0) to intArrayOf(0, 1, 0, -1) val box = Array(n) { IntArray(m) } val vis = Array(n) { BooleanArray(m) { false } }
for (i in0 until n) { for (j in0 until m) { box[i][j] = nextInt() } }
val queue: Queue<Pair<Int, Int>> = LinkedList()
for (i in0 until n) { for (j in0 until m) { if (box[i][j] == 1) { queue.offer(i to j) vis[i][j] = true } } }
val temp = mutableListOf<Pair<Int, Int>>()
while (queue.isNotEmpty()) { for (rottenNum in0 until queue.size) { val (curX, curY) = queue.poll()
for (dir in0 until 4) { val (nx, ny) = curX + dx[dir] to curY + dy[dir]
if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue if (box[nx][ny] == 1 || box[nx][ny] == -1 || vis[nx][ny]) continue
funmain() = with(Scanner(System.`in`)) { var date = 0 val (m, n) = nextInt() to nextInt() val (dx, dy) = intArrayOf(1, 0, -1, 0) to intArrayOf(0, 1, 0, -1) val box = Array(n) { IntArray(m) } val dist = Array(n) { IntArray(m) } // 익은 토마토가 들어있거나 토마토가 없는 칸은 값이 0 val queue: Queue<Pair<Int, Int>> = LinkedList()
for (i in0 until n) { for (j in0 until m) { box[i][j] = nextInt() when (box[i][j]) { 1 -> queue.offer(i to j) // 익은 토마토, 즉 거리가 0인 칸을 큐에 넣음 0 -> dist[i][j] = -1// 익지 않은 토마토의 dist값을 -1로 설정 } } }
while (queue.isNotEmpty()) { val (curX, curY) = queue.poll()
for (dir in0 until 4) { val (nx, ny) = curX + dx[dir] to curY + dy[dir]
if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue if (dist[nx][ny] >= 0) continue
dist[nx][ny] = dist[curX][curY] + 1 queue.offer(nx to ny) } }
for (i in0 until n) { for (j in0 until m) { if (dist[i][j] == -1) { // 익지 않은 토마토가 있다면 -1 출력 print(-1) return }
funmain() = with(Scanner(System.`in`)) { val (row, col) = nextInt() to nextInt() val (dx, dy) = intArrayOf(1, 0, -1, 0) to intArrayOf(0, 1, 0, -1) val maze = Array(row) { CharArray(col) } val fireDist = Array(row) { IntArray(col) { -1 } } // 불의 전파 시간 val jihoonDist = Array(row) { IntArray(col) { -1 } } // 지훈이의 이동 시간 val fireQueue: Queue<Pair<Int, Int>> = LinkedList() val jihoonQueue: Queue<Pair<Int, Int>> = LinkedList()
for (i in0 until row) { val line = next() for (j in0 until col) { maze[i][j] = line[j]
if (maze[i][j] == 'F') { fireQueue.offer(i to j) fireDist[i][j] = 0 } if (maze[i][j] == 'J') { jihoonQueue.offer(i to j) jihoonDist[i][j] = 0 } } }
// 불에 대한 BFS while (fireQueue.isNotEmpty()) { val (curX, curY) = fireQueue.poll()
for (dir in0 until 4) { val (nx, ny) = curX + dx[dir] to curY + dy[dir]
if (nx < 0 || nx >= row || ny < 0 || ny >= col) continue if (fireDist[nx][ny] >= 0 || maze[nx][ny] == '#') continue
fireDist[nx][ny] = fireDist[curX][curY] + 1 fireQueue.offer(nx to ny) } }
// 지훈이에 대한 BFS while (jihoonQueue.isNotEmpty()) { val (curX, curY) = jihoonQueue.poll()
for (dir in0 until 4) { val (nx, ny) = curX + dx[dir] to curY + dy[dir]
// 범위를 벗어난 것은 탈출에 성공했다는 의미. 큐에 거리 순으로 들어가므로 최초에 탈출한 시간을 출력하면 됨. if (nx < 0 || nx >= row || ny < 0 || ny >= col) { println(jihoonDist[curX][curY] + 1) return }
if (jihoonDist[nx][ny] >= 0 || maze[nx][ny] == '#') continue if (fireDist[nx][ny] != -1 && fireDist[nx][ny] <= jihoonDist[curX][curY] + 1) continue // 불의 전파 시간을 조건에 추가. 지훈이 도착한 시간과 동시에, 혹은 더 빨리 불이 도착하는 자리로는 갈 수 없음.
for (i in0 until row) { next().forEachIndexed { j, char -> maze[i][j] = char ... } }
이렇게 시작점이 두 종류인 문제를 해결할 수 있게 되었다. 하지만 시작점이 두 종류인 문제에 관해서 생각해야 할 점이 추가로 존재한다. 본 문제는 지훈이의 이동은 불의 전파에 영향을 받지만 불의 전파는 지훈이의 이동에 영향을 받지 않아서 불만 먼저 전파를 쭉 시키는게 가능했다. 그러나 시작점이 A, B 두 종류가 있고, A의 전파에 B가 영향을 주고 B의 전파에도 A가 영향을 준다고 가정해본다면 어느 하나를 먼저 끝까지 전파시키는게 불가능하다. (예를 들어, 불과 소방수 내지는 불과 물이 전파되는 문제여서 둘이 만나면 뭔가 상호작용이 발생하는 케이스)
위의 케이스를 다루는 문제가 바로 BOJ 18809번, Gaaaaaaaaaarden 문제이다. 아쉽게도 이 문제는 백트래킹 기법을 추가로 알고 있어야 해결이 가능하기 때문에 당장 풀어볼 수는 없지만, 두 종류의 BFS에서 BFS를 돌 때 어느 하나가 독립적이지 않고 서로에게 영향을 준다면 위의 방법으로는 해결할 수 없다는 것을 꼭 이해해야 한다. 그런 상황에서는 시간 순으로 A와 B를 동시에 진행시켜야 한다.