본문 바로가기
문제 해결/BOJ

[백준] 소용돌이 예쁘게 출력하기

by 자잘 2023. 5. 1.

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

 

1022번: 소용돌이 예쁘게 출력하기

첫째 줄에 네 정수 r1, c1, r2, c2가 주어진다.

www.acmicpc.net

1. 문제 이해

1이 위치하는 좌표를 (0, 0)이라고 했을 때 밑 사진과 같이 반시계로 소용돌이 모양으로 숫자를 채워나갈 때 (r1,c1) ~ (r2, c2)까지 범위의 숫자들을 '예쁘게' 출력하면 됩니다.

2. 문제 접근

1을 시작으로 오른쪽 아래의 숫자들의 증가폭이 8, 16, 24가 됨을 알 수 있었습니다. 이를 활용하여 사각형의 테두리에서 가장 큰 숫자를 얻을 수 있습니다. 그리고 각 숫자들은 행과 열의 값 중 절대값이 더 큰 값을 n이라고 했을 때 n + 1번째 사각형에 속하게 됩니다.

예를 들어 34는 (-3, 0)이므로 4번째 사각형에 속하게 됩니다. 현재까지 (r, c)가 주어졌을 때 몇번째 사각형에 속해있고 해당 사각형에서 가장 큰 숫자가 무엇인지 알게 되었습니다. 이를 활용하여 (r, c)에 어떤 숫자가 있는지 알아낼 수 있습니다. 각각의 사각형은 4개의 변으로 이루어져 있습니다. 현재가 n번째 사각형이라고 했을 때 밑변은 행이 n - 1, 왼쪽변은 열이 -(n - 1), 윗변은 행이 -(n - 1), 오른쪽 변은 열이 n - 1값을 갖습니다. 이를 활용하여 (r, c)가 어느 변에 위치하는지 알 수 있습니다. 각각의 변에서 시작 숫자를 정해주고 시작 숫자와 차이가 나는 칸수만큼 빼주면 (r, c)의 숫자를 알 수 있습니다. 

 

34를 예로 들면 먼저 시작숫자는 가장 큰 숫자인 49부터 시작하여 밑변 -> 왼쪽 변 -> 윗변 -> 오른쪽 변 순서로 탐색하게 됩니다. 밑변에 없으므로 왼쪽변으로 이동하는데 이때 시작 숫자를 43(=49 - 2 * (4 - 1))으로 변경해줍니다. 왼쪽 변에도 없으므로 시작숫자를 37로 변경해줍니다. 윗변에는 (-3, 0)이 존재하므로 시작 숫자의 위치와 몇칸 차이나는지 계산해주어 리턴해주면 됩니다.

3. 풀이

import sys

sys.stdin = open("input.txt", "r")
r1, c1, r2, c2 = tuple(map(int, input().split()))

board = [
    [0] * (c2 - c1 + 1)
    for _ in range(r2 - r1 + 1)
]

def getStartNumber(n):
    start = 1
    for i in range(n + 1):
        start += 8 * i
    return start


def getNumber(y, x):
    n = max(abs(y), abs(x))

    #시작 숫자(현재 사각형에서 제일 큰 숫자)
    startNumber = getStartNumber(n)

    #현재 위치
    curY, curX = n, n

    # 밑변
    if y == n:
        return startNumber - (curX - x)


    curX *= -1
    startNumber -= 2 * n

    # 왼변
    if x == -n:
        return startNumber - (curY - y)

    startNumber -= 2 * n
    curY *= -1

    # 윗변
    if y == -n:
        return startNumber - (x - curX)

    curX *= -1
    startNumber -= 2 * n

    # 오른변
    if x == n:
        return startNumber - (y - curY)


max_length = 0

for i in range(r2 - r1 + 1):
    for j in range(c2 - c1 + 1):
        board[i][j] = getNumber(i + r1, j + c1)

        max_length = max(len(str(board[i][j])), max_length)

for i in range(r2 - r1 + 1):
    for j in range(c2 - c1 + 1):
        for k in range(max_length - len(str(board[i][j]))):
            print(' ', end='')
        print(board[i][j], end =' ')
    print()

'문제 해결 > BOJ' 카테고리의 다른 글

[백준] 스위치  (0) 2023.05.03
[백준] 배열 돌리기 4  (0) 2023.05.02
[백준] 등산 마니아  (0) 2023.04.30
[백준] 무기공학  (0) 2023.04.29
[백준] 프렉탈 평면  (0) 2023.04.27