문제 풀이/백준

[백준] 1913번. 달팽이(Kotlin)

27200 2025. 10. 15. 17:52

문제

https://www.acmicpc.net/problem/1913


풀이(20분)

import java.io.BufferedReader
import java.io.InputStreamReader

fun main() {
    val br = BufferedReader(InputStreamReader(System.`in`))
    val sb = StringBuilder()

    val N = br.readLine().toInt()
    val target = br.readLine().toInt()

    val arr = Array(N) { Array(N) { 0 } }

    // 하, 우, 상, 좌 방향 (달팽이 순서)
    val dx = arrayOf(1, 0, -1, 0)
    val dy = arrayOf(0, 1, 0, -1)

    var x = 0
    var y = 0
    var dir = 0

    // 달팽이 숫자 채우기 (N*N부터 1까지)
    for (num in N * N downTo 1) {
        arr[x][y] = num
        var nx = x + dx[dir]
        var ny = y + dy[dir]

        // 다음 위치가 범위를 벗어나거나 이미 방문한 경우 방향 전환
        if (nx !in 0 until N || ny !in 0 until N || arr[nx][ny] != 0) {
            dir = (dir + 1) % 4
            nx = x + dx[dir]
            ny = y + dy[dir]
        }

        x = nx
        y = ny
    }

    var targetX = 0
    var targetY = 0

    // 결과 출력 + target 위치 찾기
    for (i in 0 until N) {
        for (j in 0 until N) {
            sb.append(arr[i][j]).append(' ')
            if (arr[i][j] == target) {
                targetX = i + 1
                targetY = j + 1
            }
        }
        sb.append('\n')
    }

    sb.append("$targetX $targetY")
    println(sb)
}

문제 풀이 전략

 

💡 핵심 아이디어

  1. 달팽이 이동 패턴을 이용해 방향 배열(dx, dy) 정의
    • 순서: ↓ → ↑ ←
    • 방향 전환은 “다음 칸이 범위를 벗어나거나 이미 채워진 경우”에 수행
  2. 1 -> N*N을 채우는 것이 아닌 N*N -> 1로 채우기
  3. 채우는 과정 중 target 값을 만나면
    그 좌표를 저장했다가 마지막에 출력.

⚙️ 풀이 과정

  1. arr[x][y] = 현재 숫자
  2. 다음 칸으로 이동 (nx = x + dx[dir], ny = y + dy[dir])
  3. 만약
    • 배열 범위를 벗어나거나
    • 이미 채워진 칸이라면
      → 방향을 시계 방향으로 전환 (dir = (dir + 1) % 4)
  4. 모든 칸을 채운 뒤, target 위치를 찾아 출력.