본문 바로가기
  • 개발하는 곰돌이
Algorithm/BOJ

[Kotlin] 백준 30036 : INK

by 개발하는 곰돌이 2023. 10. 25.

문제 링크

 

30036번: INK

첫 번째 줄에 정수 $I$, $N$, $K$가 공백으로 구분되어 주어진다. $(1 \le I, N, K \le 100)$ 두 번째 줄에는 잉크 문자열이 주어진다. 세 번째 줄부터 $N$개의 줄에 걸쳐 $N \times N$ 크기의 스테이지가 주어진

www.acmicpc.net


문제 해설

특별한 알고리즘이 필요하지 않은 단순 구현 문제.

 

우선 스테이지를 입력받으면서 하얀 사각형의 현재 위치를 저장하고 충전된 잉크의 양과 현재 색상의 순서를 저장할 변수를 선언한다. 이때 하얀 사각형의 현재 위치인 @는 이후 구현을 편하게 하기 위해 .으로 치환해준다.

 

이후 문제의 조건을 차례대로 구현해보자.

 

  • UDLR : 스테이지를 벗어나지 않는 범위 내에서, 스테이지의 목적지 값이 .인 경우(장애물로 막혀있지 않은 경우)에만 각각 상하좌우로 현재 위치를 옮긴다.
'U' -> if (r >= 1 && map[r - 1][c] == '.') r--
'D' -> if (r < n - 1 && map[r + 1][c] == '.') r++
'L' -> if (c >= 1 && map[r][c - 1] == '.') c--
'R' -> if (c < n - 1 && map[r][c + 1] == '.') c++
  • j : 충전된 잉크의 양을 1 증가시킨다.
  • J : 모든 스테이지를 순회하면서 하얀 사각형의 현재 위치를 \((r,c)\)라고 할 때, \(\left|r-i\right|+\left|c-j\right|\)가 충전된 잉크의 양 이하인 \((i,j)\) 중, 값이 .이 아닌 모든 구역(= 장애물이 있는 구역)을 현재 잉크의 색상으로 변경한다. 이후 충전된 잉크의 양을 0으로 변경한다.
for (i in 0 until n) {
    for (j in 0 until n) {
        if (abs(r - i)  + abs(c - j) <= chargedInk && map[i][j] != '.') map[i][j] = ink[currentColor]
    }
}
chargedInk = 0
  • 현재 잉크의 색상은 점프할 때마다 변경한다. 설명이 약간 난해하긴 한데, 예시를 통해 로테이션을 도는 구조라는 것을 알 수 있다.
currentColor = (currentColor + 1) % I

커맨드 처리가 모두 끝났다면 최종적으로 \((r,c)\) 위치의 값을 @로 변경해서 스테이지 내용을 출력한다.

Code

import kotlin.math.abs

fun main() = with(System.`in`.bufferedReader()) {
    val (I, n, k) = readLine().split(' ').map { it.toInt() }
    val ink = readLine().toCharArray()
    var (r, c) = 0 to 0
    val map = Array(n) { readLine().toCharArray() }
    loop@ for (i in 0 until n) {
        for (j in 0 until n) {
            if (map[i][j] == '@') {
                map[i][j] = '.'
                r = i
                c = j
                break@loop
            }
        }
    }
    val command = readLine()
    var chargedInk = 0
    var currentColor = 0
    for (com in command) {
        when (com) {
            'U' -> if (r >= 1 && map[r - 1][c] == '.') r--
            'D' -> if (r < n - 1 && map[r + 1][c] == '.') r++
            'L' -> if (c >= 1 && map[r][c - 1] == '.') c--
            'R' -> if (c < n - 1 && map[r][c + 1] == '.') c++
            'j' -> chargedInk++
            'J' -> {
                for (i in 0 until n) {
                    for (j in 0 until n) {
                        if (abs(r - i)  + abs(c - j) <= chargedInk && map[i][j] != '.') map[i][j] = ink[currentColor]
                    }
                }
                chargedInk = 0
                currentColor = (currentColor + 1) % I
            }
        }
    }
    map[r][c] = '@'
    println(map.joinToString("\n") { it.joinToString("") })
}

댓글