본문 바로가기

카테고리 없음

[BOJ] 16926 배열 돌리기 1 Python (복습 필요)

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

 

16926번: 배열 돌리기 1

크기가 N×M인 배열이 있을 때, 배열을 돌려보려고 한다. 배열은 다음과 같이 반시계 방향으로 돌려야 한다. A[1][1] ← A[1][2] ← A[1][3] ← A[1][4] ← A[1][5] ↓ ↑ A[2][1] A[2][2] ← A[2][3] ← A[2][4] A[2][5]

www.acmicpc.net

배열 돌리기 1

 
시간 제한메모리 제한제출정답맞힌 사람정답 비율
1 초 512 MB 12089 5794 3833 46.721%

문제

크기가 N×M인 배열이 있을 때, 배열을 돌려보려고 한다. 배열은 다음과 같이 반시계 방향으로 돌려야 한다.

A[1][1] ← A[1][2] ← A[1][3] ← A[1][4] ← A[1][5]
   ↓                                       ↑
A[2][1]   A[2][2] ← A[2][3] ← A[2][4]   A[2][5]
   ↓         ↓                   ↑         ↑
A[3][1]   A[3][2] → A[3][3] → A[3][4]   A[3][5]
   ↓                                       ↑
A[4][1] → A[4][2] → A[4][3] → A[4][4] → A[4][5]

예를 들어, 아래와 같은 배열을 2번 회전시키면 다음과 같이 변하게 된다.

1 2 3 4       2 3 4 8       3 4 8 6
5 6 7 8       1 7 7 6       2 7 8 2
9 8 7 6   →   5 6 8 2   →   1 7 6 3
5 4 3 2       9 5 4 3       5 9 5 4
 <시작>         <회전1>        <회전2>

배열과 정수 R이 주어졌을 때, 배열을 R번 회전시킨 결과를 구해보자.

입력

첫째 줄에 배열의 크기 N, M과 수행해야 하는 회전의 수 R이 주어진다.

둘째 줄부터 N개의 줄에 배열 A의 원소 Aij가 주어진다.

출력

입력으로 주어진 배열을 R번 회전시킨 결과를 출력한다.

 

풀이 (시간초과)

import sys
input = sys.stdin.readline
import copy

n, m, r = map(int, input().split())
graph = []
for i in range(n):
    graph.append(list(map(int, input().split())))

dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]
turned_graph = [[0]*m for _ in range(n)]
for _ in range(r):
    for i in range(n//2):
        tmp = i
        for j in range(tmp, m):
            if j == m-tmp:
                continue
            # 왼쪽 방향
            nx, ny = i+dx[2], j+dy[2]
            if 0<= nx < n and 0+tmp<= ny < m:
                turned_graph[nx][ny] = graph[i][j]

    for i in range(n-1, n//2-1, -1):
        tmp = n-i-1
        for j in range(tmp, m):
            if j == m-tmp:
                continue
            # 오른쪽 방향
            nx, ny = i + dx[3], j + dy[3]
            if 0<= nx < n and 0<= ny < m:
                turned_graph[nx][ny] = graph[i][j]
    for i in range(m//2):
        tmp = i
        for j in range(tmp, n):
            if j == n-tmp:
                continue
            # 아래 방향
            nx, ny = j + dx[1], i + dy[1]
            if 0+tmp <= nx < n-tmp and 0 <= ny < m:
                turned_graph[nx][ny] = graph[j][i]

    for i in range(m-1, m//2-1, -1):
        tmp = m-i-1
        for j in range(tmp, n):
            if j == n-tmp:
                continue
            # 윗 방향
            nx, ny = j + dx[0], i + dy[0]
            if 0+tmp <= nx < n-tmp and 0 <= ny < m:
                turned_graph[nx][ny] = graph[j][i]
    graph = copy.deepcopy(turned_graph)

for i in turned_graph:
    print(*i)

이차원 배열로 두고 풀었는데, 시간초과가 났다.

이 코드를 짜는데도 디버깅 하는 부분에서 오랜 시간이 걸렸다.

첫 번째 둘레와 두 번째 둘레가 독립적으로 회전하는 규칙이 있는데, 이걸 2차원 리스트로 한꺼번에 돌리려 하니

for문을 사용할 때 인덱싱 부분 처리에서 매우 복잡했다.

그래서 인덱싱 오류가 많았고 이를 하나하나 고치는데 많은 시간이 걸렸다. ㅠ

 

풀이 (참고한 풀이) 2차원 리스트를 1차원 배열로 바꿔서 풀어주기

참고 : https://velog.io/@leetaekyu2077/%EB%B0%B1%EC%A4%80-16926%EB%B2%88-%EB%B0%B0%EC%97%B4-%EB%8F%8C%EB%A6%AC%EA%B8%B0-1

 

[Python] 백준 16926번: 배열 돌리기 1

백준 16926번: 배열 돌리기 1 문제 풀이에 대한 기록입니다.

velog.io

아이디어는 다음과 같다.

왼쪽 상단 원소를 껍질의 시작점이라 가정하고, 시작 상태 배열에서의 각 껍질을 시계방향으로 순서대로 나열하면 다음과 같아진다.

첫 번째 껍질 : 1 2 3 4 8 6 2 3 4 5 9 5
두 번째 껍질 : 6 7 7 8

이 상태에서 회전시키는 것은 아주아주 쉽다.

맨 앞에서부터 R개의 원소를 잘라 맨 뒤에 붙여주기만 하면 된다.

첫 번째 껍질 2번 회전 후 : 3 4 8 6 2 3 4 5 9 5 1 2
두 번째 껍질 2번 회전 후 : 7 8 6 7

이 문제는 각 테두리가 독립적으로 움직이는 원리를 이용해서 푸는 문제였다.

따라서 무식하게 for문으로 꾸역꾸역 구현하는게 아니라 문제의 의도를 파악하고 원리를 최대한 이용해서 풀어야 한다.😂

 

먼저, deque관련 함수 몇개 공부

1. rotate()

# Contain 1, 2, 3, 4, 5 in deq
deq = deque([1, 2, 3, 4, 5])

deq.rotate(1)
print(deq)
# deque([5, 1, 2, 3, 4])

deq.rotate(-1)
print(deq)
# deque([1, 2, 3, 4, 5])

2. clear()

모든 원소를 지운다.

 

3. extend()

리스트 전체를 삽입할때 사용한다.

 

전체 풀이 코드

from sys import stdin
from collections import deque

N, M, R = map(int, stdin.readline().split())

matrix = []
answer = [[0]*M for _ in range(N)]
deq = deque()

for i in range(N):
    matrix.append(list(stdin.readline().split()))

# 각 껍질별로 나누어 작업하기 위해서 배열의 행과 열인 N, M 중 짝수인 쪽의 절반(껍질의 개수가 됨) 만큼 for문을 반복시킨다.
loops = min(N, M) // 2
for i in range(loops):
    deq.clear()
    deq.extend(matrix[i][i:M-i])
    deq.extend([row[M-i-1] for row in matrix[i+1:N-i-1]])
    deq.extend(matrix[N-i-1][i:M-i][::-1])
    deq.extend([row[i] for row in matrix[i+1:N-i-1]][::-1])
    
    deq.rotate(-R)
    
    for j in range(i, M-i):                 # 위쪽
        answer[i][j] = deq.popleft()
    for j in range(i+1, N-i-1):             # 오른쪽
        answer[j][M-i-1] = deq.popleft()
    for j in range(M-i-1, i-1, -1):           # 아래쪽
        answer[N-i-1][j] = deq.popleft()  
    for j in range(N-i-2, i, -1):           # 왼쪽
        answer[j][i] = deq.popleft()    

for line in answer:
    print(" ".join(line))

 

코드 복습하고 ✔️

혼자 다시 짜보기