문제 출처 : https://www.acmicpc.net/problem/1022
문제
크기가 무한인 정사각형 모눈종이가 있다. 모눈종이의 각 정사각형은 행과 열의 쌍으로 표현할 수 있다.
이 모눈종이 전체를 양의 정수의 소용돌이 모양으로 채울 것이다. 일단 숫자 1을 0행 0열에 쓴다. 그리고 나서 0행 1열에 숫자 2를 쓴다. 거기서 부터 소용돌이는 반시계 방향으로 시작된다. 다음 숫자는 다음과 같이 채우면 된다.
-3 -2 -1 0 1 2 3
--------------------
-3 |37 36 35 34 33 32 31
-2 |38 17 16 15 14 13 30
-1 |39 18 5 4 3 12 29
0 |40 19 6 1 2 11 28
1 |41 20 7 8 9 10 27
2 |42 21 22 23 24 25 26
3 |43 44 45 46 47 48 49
이 문제는 위와 같이 채운 것을 예쁘게 출력하면 된다. r1, c1, r2, c2가 입력으로 주어진다. r1, c1은 가장 왼쪽 위 칸이고, r2, c2는 가장 오른쪽 아래 칸이다.
예쁘게 출력한다는 것은 다음과 같이 출력하는 것이다.
- 출력은 r1행부터 r2행까지 차례대로 출력한다.
- 각 원소는 공백으로 구분한다.
- 모든 행은 같은 길이를 가져야 한다.
- 공백의 길이는 최소로 해야 한다.
- 모든 숫자의 길이(앞에 붙는 공백을 포함)는 같아야 한다.
- 만약 수의 길이가 가장 길이가 긴 수보다 작다면, 왼쪽에서부터 공백을 삽입해 길이를 맞춘다.
입력
첫째 줄에 네 정수 r1, c1, r2, c2가 주어진다.
출력
r2 - r1 + 1개의 줄에 소용돌이를 예쁘게 출력한다.
제한
- -5 000 ≤ r1, c1, r2, c2 ≤ 5,000
- 0 ≤ r2 - r1 ≤ 49
- 0 ≤ c2 - c1 ≤ 4
알고리즘 분류
풀이
구현 문제다.
범위를 설정하는 여러가지 방법이 있을 것 같다.
본인은 정답만을 저장할 배열을 딱 맞는 크기 0~n, 0~m 로 만들었다.
그리고 원래 0,0이 있던 자리(시작점)을 이동한 정답 배열에 맞게 새로 잡아 주었다.
r2-r1+1, c2-c1+1로 정답 배열의 크기를 구할 수 있다.
예제 1번의 경우
r1 = -3
c1 = -3
r2 = 2
c2 = 0
정답 배열은 arr[5][4]가 된다.
r,c를 시작점으로 잡고 r,c에서 소용돌이로 움직이며 정답 배열의 인덱스에 포함되는 경우 값을 넣고,
아닌 경우 그냥 숫자만 증가하고 스킵한다.
위의 정답 배열은 r1을 0으로 3만큼 땡기고, c1도 0으로 3만큼 땡긴 형태이다.
따라서 시작점 r,c도 같이 땡겨주면 r=3, c=3이 시작점이 된다.
이제 이 시작점에 1을 넣고 소용돌이를 돌리면 된다.
예제 2번의 경우
r1 = -2
c1 = 2
r2 = 0
c2 = 3
정답 배열은arr[3][2]가 된다.
시작점은 r1을 0으로 2만큼 땡겼기 때문에
r = 2
c는 둘 다 양수라서 땡기지 않았으니
c = 0이다.
하지만 정답 배열은 0,0인덱스부터 시작하니 오히려 c는 -2만큼 이동해야 원래 0이 있던 자리에서 시작할 수 있다.
즉 r = 2, c=-2 가 시작점이 되고 여기서부터 소용돌이를 돌리면 된다.
아래 그래프를 그려보는 게 직빵이다.
0 | 1 | 2 | 3 | |
-2 | 정답범위 | 정답범위 | ||
-1 | 정답범위 | 정답범위 | ||
0 | 시작점 | 정답범위 | 정답범위 |
-2 | -1 | 0 | 1 | 2 | 3 | |
-2 | ||||||
-1 | ||||||
0 | 정답범위 | 정답범위 | ||||
1 | 정답범위 | 정답범위 | ||||
2 | 시작점 | 정답범위 | 정답범위 |
코드
val br = System.`in`.bufferedReader()
fun getIntList() = br.readLine().split(' ').map { it.toInt() }
fun getInt() = br.readLine().toInt()
val dir = arrayOf(
arrayOf(0, 1),
arrayOf(-1, 0),
arrayOf(0, -1),
arrayOf(1, 0),
)
lateinit var graph: Array<IntArray>
fun main() = with(System.out.bufferedWriter()) {
var( r1, c1, r2, c2) = getIntList()
var r = 0
var c = 0
graph = Array(r2-r1+1){ IntArray(c2-c1+1) }
if(r1<0){
r2 -=r1
r = -r1
r1 =0
}
else{
r = -r1
}
if(c1<0){
c2 -=c1
c = -c1
c1 = 0
}
else{
c = -c1
}
var maxNum = 0
var num = 1
var len = 1
var d = 0
if(r in graph.indices && c in graph[0].indices) graph[r][c] = num
while (true) {
for (i in 0 until len) {
r += dir[d % 4][0]
c += dir[d % 4][1]
++num
if(r in graph.indices && c in graph[0].indices) {
graph[r][c] = num
maxNum = maxNum.coerceAtLeast(graph[r][c])
}
}
if (++d % 2 == 0) {
len++
}
if (graph[0][0] != 0 && graph[0][graph[0].size-1] != 0 && graph[graph.size-1][graph[0].size-1] != 0 && graph[graph.size-1][0] != 0) {
break
}
}
val maxLen = maxNum.toString().length
for (i in graph.indices) {
for (j in graph[0].indices) {
write("${String.format("%${maxLen}d", graph[i][j])} ")
}
write("\n")
}
close()
}
'알고리즘 문제 풀이 > 백준' 카테고리의 다른 글
백준 4485 녹색 옷 입은 애가 젤다지? Kotlin (다익스트라) (0) | 2022.07.06 |
---|---|
백준 14499 주사위 굴리기 Kotlin (구현) (0) | 2022.07.05 |
백준 14891 톱니바퀴 Kotlin (구현) (0) | 2022.07.03 |
백준 23289 온풍기 안녕! Kotlin (시뮬레이션) (0) | 2022.07.01 |
백준 18115 카드 놓기 Kotlin (덱) (0) | 2022.06.30 |
댓글