๋ฌธ์
ํ์ด ์ธ์ด
Kotlin
์ฝ๋
import java.util.*
data class Point(
val x: Int,
val y: Int
)
data class Points(
val red_x: Int,
val red_y: Int,
val blue_x: Int,
val blue_y: Int,
val depth: Int
)
data class Infos(
val x: Int,
val y: Int,
val cnt: Int
)
lateinit var array: Array<Array<String>>
val dx = arrayOf(1, -1, 0, 0)
val dy = arrayOf(0, 0, 1, -1)
var n = 0
var m = 0
var red = Point(0, 0)
var blue = Point(0, 0)
fun main() = with(Scanner(System.`in`)) {
n = nextInt()
m = nextInt()
array = Array(n) { Array(m) { "" } }
for (i in 0 until n) {
val input = next().chunked(1)
for (j in 0 until m) {
array[i][j] = input[j]
}
}
// ์ฐ์ R, B์ ์ขํ๋ฅผ ์ฐพ์
find()
// ํ์
bfs()
}
fun find() {
for (i in 0 until n) {
for (j in 0 until m) {
if (array[i][j] == "#" || array[i][j] == ".") continue
else if (array[i][j] == "R") red = Point(i, j)
else if (array[i][j] == "B") blue = Point(i, j)
}
}
}
fun bfs() {
var visited = Array(n) { Array(m) { Array(n) { Array(m) { 0 } } } }
var map = LinkedList<Points>()
map.add(Points(red.x, red.y, blue.x, blue.y, 1))
visited[red.x][red.y][blue.x][blue.y] = 1
while (map.isNotEmpty()) {
val current = map.poll()
if (current.depth > 10) break
for (i in 0..3) {
var redInfos = move(current.red_x, current.red_y, dx[i], dy[i])
var blueInfos = move(current.blue_x, current.blue_y, dx[i], dy[i])
if (array[blueInfos.x][blueInfos.y] == "O") continue
if (array[redInfos.x][redInfos.y] == "O") {
println(1)
return
}
if (redInfos.x == blueInfos.x && redInfos.y == blueInfos.y) {
if (redInfos.cnt > blueInfos.cnt) {
redInfos = Infos(redInfos.x - dx[i], redInfos.y - dy[i], redInfos.cnt)
} else {
blueInfos = Infos(blueInfos.x - dx[i], blueInfos.y - dy[i], blueInfos.cnt)
}
}
val points = Points(redInfos.x, redInfos.y, blueInfos.x, blueInfos.y, current.depth + 1)
if (visited[points.red_x][points.red_y][points.blue_x][points.blue_y] == 1) continue
visited[points.red_x][points.red_y][points.blue_x][points.blue_y] = 1
map.add(points)
}
}
println(0)
}
fun move(x: Int, y: Int, dx: Int, dy: Int): Infos {
var nx = x
var ny = y
var cnt = 0
while (array[nx + dx][ny + dy] != "#" && array[nx][ny] != "O") {
nx += dx
ny += dy
cnt += 1
}
return Infos(nx, ny, cnt)
}
ํ์ด ๋ฐฉ๋ฒ
BFS(ํน์ DFS)
๋ฅผ ํ์ฉํ ๊ตฌํ ๋ฌธ์ ์ด๋ค. ๊ตฌ์ฌ์ด ๋ค์ด์๋ ์ง์ฌ๊ฐํ ๋ณด๋๋ฅผ ์ด๋ฆฌ์ ๋ฆฌ ๊ตด๋ ค์ ๋นจ๊ฐ ๊ตฌ์ฌ์ ํ๋ ๊ตฌ์ฌ๋ณด๋ค ๋จผ์ ํ์ถ์ํค๋ฉด ๋๋ค. ๊ตฌํ ๋ฌธ์ ๋๊น ๊ท์น์ ์ฐพ์๋ณด์.
1. ์ฐ์ ์ง์ฌ๊ฐํ ๋ณด๋๋ ๊ฐ์ฅ์๋ฆฌ๊ฐ ๋ฒฝ์ผ๋ก ๋๋ฌ์์ฌ์๋ค. ๋ฐ๋ผ์ BFS ํ์ ๊ณผ์ ์์ ๋ฒ์๋ฅผ ๋ฒ์ด๋ ์ผ์ด ์๋ค.
2. ํ์ง๋ง ์ผ๋ฐ์ ์ธ BFS ๋ฌธ์ ์ ๋ค๋ฅด๊ฒ ์ง์ฌ๊ฐํ ๋ณด๋๋ฅผ ํ์ชฝ์ผ๋ก ๊ธฐ์ธ์ด๋ฉด ๋ฒฝ์ด๋ ๊ตฌ๋ฉ์ ๋ง๋ ๋๊น์ง ์ง์งํ๋ค.
3. ํน์ ํด๋น ๊ตฌ์ฌ๋ณด๋ค ์์ ๊ตฌ์ฌ์ด ์๋ ๊ฒฝ์ฐ ํด๋น ๊ตฌ์ฌ๊ณผ ํจ๊ป ์ด๋ํ๊ฒ ๋๋ค.
ex) (<-์ด๋๋ฐฉํฅ-) ๋นจ๊ฐ ๊ตฌ์ฌ, ํ๋ ๊ตฌ์ฌ ํญ์ ์ด ํํ๋ฅผ ์ ์งํ๋ค.
์ด ์ ๋์ ๊ท์น์ ๊ฐ์ง๊ณ ์๊ณ ์ด์ ๊ตฌํํ๋ฉด ๋๋ค.
1. ์ขํ์ ๋ํ ์ ๋ณด๋ฅผ ํจ์จ์ ์ผ๋ก ์ ์ฅํ๊ธฐ ์ํด data class
๋ฅผ ์ ์ํ๋ค. Pair
๋ Triple
์ ์ฌ์ฉํด๋ ๋๋ค.
data class Point(
val x: Int,
val y: Int
)
data class Points(
val red_x: Int,
val red_y: Int,
val blue_x: Int,
val blue_y: Int,
val depth: Int
)
data class Infos(
val x: Int,
val y: Int,
val cnt: Int
)
2. ์
๋ ฅ ๊ฐ์ ๋ฐฐ์ด์ ์ ์ฅํ๋ค. ๋์ด์ฐ๊ธฐ
๊ฐ ๋์ด ์์ง ์์ ์
๋ ฅ ๊ฐ์ split
ํด์ผํ๋ฏ๋ก chunked
๋ฅผ ์ฌ์ฉํด์ ๋ถ๋ฆฌํ๋ค.
array = Array(n) { Array(m) { "" } }
for (i in 0 until n) {
val input = next().chunked(1)
for (j in 0 until m) {
array[i][j] = input[j]
}
}
3. ๋นจ๊ฐ ๊ตฌ์ฌ
๊ณผ ํ๋ ๊ตฌ์ฌ
์ ์ขํ๋ฅผ ํ์ํ๋ค. ์ด๊ธฐ์ ์ ์ํ Point data class
๋ฅผ ํ์ฉํ๋ค.
fun find() {
for (i in 0 until n) {
for (j in 0 until m) {
if (array[i][j] == "#" || array[i][j] == ".") continue
else if (array[i][j] == "R") red = Point(i, j)
else if (array[i][j] == "B") blue = Point(i, j)
}
}
}
4. ํด๋น ์ขํ๋ฅผ ๊ฐ์ง๊ณ BFS
๋ฅผ ์งํํ๋ฉด์ ๋นจ๊ฐ ๊ตฌ์ฌ์ ํ์ถ ์ฌ๋ถ๋ฅผ ํ๋จํ๋ฉด ๋๋ค. ๊ทธ ์ ์ ๊ธฐ์กด BFS
๋ฌธ์ ์๋ ๋ค๋ฅด๊ฒ ํ ์นธ์ฉ ์ด๋ํ๋ ๊ฒ์ด ์๋ ๋ฒฝ์ ๋ง๋๊ฑฐ๋ ๊ตฌ๋ฉ, ํน์ ๋ค๋ฅธ ๊ตฌ์ฌ์ ๋ง๋ ๋๊น์ง ์ง์งํ๋ ํน์ฑ์ด ์์ผ๋ฏ๋ก ์ด์ ๊ด๋ จ๋ move
ํจ์๋ฅผ ๋ณ๋๋ก ์ ์ํ๋ค. cnt
๋ฅผ ์นด์ดํธํ๋ ์ด์ ๋ ๋นจ๊ฐ ๊ตฌ์ฌ๊ณผ ํ๋ ๊ตฌ์ฌ์ด ๊ฐ์ ์ง์ ์ ์กด์ฌํ ์ ์๋๋ฐ ์ด ๋ ์ฒ๋ฆฌ๋ฅผ ํด์ฃผ๊ธฐ ์ํด์ ์ด๋ฅผ ์นด์ดํธํ๋ค.
fun move(x: Int, y: Int, dx: Int, dy: Int): Infos {
var nx = x
var ny = y
var cnt = 0
while (array[nx + dx][ny + dy] != "#" && array[nx][ny] != "O") {
nx += dx
ny += dy
cnt += 1
}
return Infos(nx, ny, cnt)
}
5. ์ด์ ์ง์ง๋ก ํ์์ ์งํํ๋ฉด ๋๋ค. ์ฝ๋๊ฐ ์ข ๊ธธ๋ค.
fun bfs() {
var visited = Array(n) { Array(m) { Array(n) { Array(m) { 0 } } } }
var map = LinkedList<Points>()
map.add(Points(red.x, red.y, blue.x, blue.y, 1))
visited[red.x][red.y][blue.x][blue.y] = 1
while (map.isNotEmpty()) {
// linkedList๋ก queue ๊ตฌํ
val current = map.poll()
// 10ํ ์ด๋ด์ ํ์ถํ์ง ๋ชปํ๋ฉด ์คํจ
if (current.depth > 10) break
// ์, ํ, ์ข, ์ฐ ํ์ ์งํ
for (i in 0..3) {
// ๋ฒฝ, ํ์ถ๊ตฌ๋ฅผ ๋ง๋ ๋๊น์ง ์ง์ง
var redInfos = move(current.red_x, current.red_y, dx[i], dy[i])
var blueInfos = move(current.blue_x, current.blue_y, dx[i], dy[i])
// ํ๋ ๊ตฌ์ฌ์ด ํ์ถํ๋ฉด ์คํจ
if (array[blueInfos.x][blueInfos.y] == "O") continue
// ๋นจ๊ฐ ๊ตฌ์ฌ์ด ํ์ถํ๋ฉด ์ฑ๊ณต
if (array[redInfos.x][redInfos.y] == "O") {
println(1)
return
}
// ๋นจ๊ฐ ๊ตฌ์ฌ๊ณผ ํ๋ ๊ตฌ์ฌ์ด ๊ฐ์ ์์น์ ์กด์ฌํ๋ฉด
if (redInfos.x == blueInfos.x && redInfos.y == blueInfos.y) {
// ์ด๋ ๊ฑฐ๋ฆฌ๋ฅผ ๋น๊ตํ์ฌ ๋ ๋ฉ๋ฆฌ ์ด๋ํ ๊ตฌ์ฌ์ ํ ์นธ ๋ค๋ก ์ด๋ํ๋ค.
if (redInfos.cnt > blueInfos.cnt) {
redInfos = Infos(redInfos.x - dx[i], redInfos.y - dy[i], redInfos.cnt)
} else {
blueInfos = Infos(blueInfos.x - dx[i], blueInfos.y - dy[i], blueInfos.cnt)
}
}
// ์ด๋ํ ์ขํ์ depth++๋ฅผ ์ ์ฅ
val points = Points(redInfos.x, redInfos.y, blueInfos.x, blueInfos.y, current.depth + 1)
// ์ด๋ฏธ ๋ฐฉ๋ฌธํ ์ขํ์ด๋ฉด continue
if (visited[points.red_x][points.red_y][points.blue_x][points.blue_y] == 1) continue
// ํด๋น ์ขํ ๋ฐฉ๋ฌธ ์ฒ๋ฆฌ
visited[points.red_x][points.red_y][points.blue_x][points.blue_y] = 1
// ์๋ก์ด ์ขํ๋ฅผ queue์ ์ฝ์
map.add(points)
}
}
println(0)
}
๊ฒฐ๊ณผ
10ํ ์ด๋ด
์ ํ์ถํ์ง ๋ชปํ ๊ฒฝ์ฐ ์ด๋ ์คํจ๋ก ๊ฐ์ฃผํ๋๋ฐ ์ด์ ๋ํ ์กฐ๊ฑด์์ ์๋ชป ์์ฑํด์ ๊ณ์ ์คํจํ๋ค. ์ด๊ธฐ์๋ ์, ํ, ์ข, ์ฐ
์ ๋ํ ํ์์ ์๋ฃํ ๊ฒฝ์ฐ์ depth++
๋ฅผ ์งํํ๋๋ฐ ์ด๋ ์๋ชป๋ ๋ฐฉ๋ฒ์ด์๋ค. ์ด๋ฅผ depth๊น์ง Points ๊ฐ์ฒด์ ์ ์ฅํ๋ ๋ฐฉ์์ผ๋ก ํด๊ฒฐํ๋ค.
'โ๏ธ ์ฝํ ์ค๋น > Implementation' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[ํ๋ก๊ทธ๋๋จธ์ค] 124 ๋๋ผ์ ์ซ์ (0) | 2022.06.09 |
---|---|
[๊ตฌํ / Kotlin] 2022 SK ICT Family ๊ฐ๋ฐ์ ์ฑ์ฉ ์ฑ๋ฆฐ์ง - 2๋ฒ (0) | 2022.03.12 |