1022번: 소용돌이 예쁘게 출력하기
첫째 줄에 네 정수 r1, c1, r2, c2가 주어진다.
www.acmicpc.net
문제
크기가 무한인 정사각형 모눈종이가 있다. 모눈종이의 각 정사각형은 행과 열의 쌍으로 표현할 수 있다.
이 모눈종이 전체를 양의 정수의 소용돌이 모양으로 채울 것이다. 일단 숫자 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개의 줄에 소용돌이를 예쁘게 출력한다.
코드
r1,c1,r2,c2 = map(int, input().split())
r, c = r2-r1+1, c2-c1+1
dx = [-1, 0, 1, 0]
dy = [0, -1, 0, 1]
num = 2
cnt = 0
paper = [[0] * c for _ in range(r)]
if 0 <= -r1 < r and 0 <= -c1 < c:
paper[-r1][-c1] = 1
cnt += 1
x, y = 1, 1
length = 2
max_num = 0
while cnt < (r*c):
for dir in range(4):
for _ in range(length):
x += dx[dir]
y += dy[dir]
# 출력할 범위 내의 숫자인 경우
if 0 <= x-r1 < r and 0 <= y-c1 < c:
cnt += 1
paper[x-r1][y-c1] = num
max_num = num
num += 1
length += 2 # 한 바퀴 돌고 나면 길이 2 추가
x += 1
y += 1
for i in range(r):
for j in range(c):
print(str(paper[i][j]).rjust(len(str(max_num))), end=' ')
print()
Python3로는 시간 초과가 발생하고 PyPy3로는 통과한다.
이렇게 하면 최대 5000*5000번 반복문을 돌기 때문인것 같다.
수학적인 방법으로 접근해서 해결하면 될 거 같은데 사실 처음 문제를 봤을 때는 규칙이 보여서 수학적으로 풀어보려다가 복잡한 거 같아서 위와 같이 해결했었다.
처음에 생각했던 방법은 아래와 같다.
소용돌이 배열을 살펴보면 위와 같이 규칙적으로 나눌 수 있는데 나눈 구역의 가장 오른쪽 아래의 숫자는 항상 구역 길이의 제곱수이다. 이 점을 이용하면 좌표 (x, y)를 입력받았을 때 그 때의 숫자를 구할 수 있을 것이다.
'문제풀이 > 구현' 카테고리의 다른 글
[Python/파이썬] 백준 17143번 낚시왕 (0) | 2023.10.11 |
---|---|
[Python/파이썬] 백준 19236번 청소년 상어 (0) | 2023.09.12 |
[Python/파이썬] 백준 17128번 소가 정보섬에 올라온 이유 (0) | 2023.07.28 |
[Python/파이썬] 백준 2115번 갤러리 (0) | 2023.07.06 |
[Python/파이썬] 백준 17779번 게리맨더링 2 (0) | 2023.06.26 |