CS/알고리즘_문제풀이(파이썬)

회전탑

Jedy_Kim 2021. 5. 26. 10:47
728x90

시간제한 1초

문제

N개의 층에 각각 M개의 숫자가 쓰여있다. 회전탑은 층에 존재하는 숫자를 회전시킬 수 있다. 회전 후 인접한 부분의 숫자가 같을 경우 회전판에서 숫자를 지운다.


[그림 1]

회전탑의 회전은 시계 방향 혹은 반시계 방향으로 가능하다. 한 번 회전시 회전되는 층은 다수가 될 수 있다. 회전시켜야할 층의 번호와 배수관계에 있는 회전판들은 모두 회전된다. 또한, 회전은 동시에 일어난다. 층을 회전한 뒤 회전한 어떠한 층에서도 지워지는 숫자가 없을 경우, 모든 층에 존재하는 숫자들의 평균을 구해 각각의 숫자와 비교한다.(평균값의 소숫점 아래는 버린다) 만약 평균보다 크면 -1을, 평균보다 작으면 +1을 더해준다. 앞서 말한 처리를 한 다음엔 다시 제거가 일어나는 것이 아닌 다음 회전이 일어난다.


[그림 2]


[그림 3]

회전탑의 정보와 회전시키는 정보가 주어졌을때, 회전을 마친 뒤 탑에 남아있는 숫자들의 합을 구해보자.

 

입력

첫 번째 줄에 테스트 케이스의 개수 T가 주어진다. 다음 줄부터 T개의 테스트 케이스에 대한 정보가 주어진다.

각각의 테스트 케이스의 첫 번째 줄에 회전판의 개수 N, 각각의 회전판에 쓰여진 숫자 개수 M, 회전 횟수 K가 공백을 통해 구분하여 주어진다.

두 번째 줄부터 N개의 줄에 걸쳐 1층부터 N층까지 각 층의 회전판에 쓰여진 숫자가 공백을 통해 구분하여 주어진다. 주어진 순서대로 인접해있으며, 첫 번째 숫자가 12시 방향의 바로 오른쪽에 적힌다. 회전판에 적히는 숫자는 100을 넘지않는 자연수다.

바로 다음 줄부터 K개의 줄에 걸쳐 회전 정보가 공백을 통해 구분하여 주어진다. 각 줄에 주어지는 회전 정보는 회전시킬 층의 번호 a, 방향 d, 회전시킬 칸 수 c 순서로 주어진다. 회전 방향은 0과 1로 주어지며, 0은 시계 방향, 1은 반시계 방향이다. (3 ≤ N, M ≤ 50, 1 ≤ K ≤ 50, 1 ≤ a ≤ N, 1 ≤ c ≤ 50)

 

출력

각 테스트 케이스에 대해 회전을 마친 뒤 회전탑에 남은 숫자들의 합을 출력한다. 각 테스트 케이스의 출력 양식은 "#t r"이다. t는 테스트 케이스의 번호이며, 1부터 시작한다. r은 문제에 대한 결과값을 뜻한다.

 

예제 입력

5

4 5 2

4 3 6 1 3

3 2 6 3 2

6 5 1 9 7

2 9 8 3 8

2 0 1

1 0 1

4 5 2

4 3 6 1 3

3 2 6 3 2

6 5 1 9 7

2 9 8 3 8

2 1 2

1 0 1

3 7 5

7 4 9 2 9 5 7

9 3 5 6 5 9 3

4 4 3 9 7 4 2

3 1 8

2 1 1

1 0 6

1 1 7

3 0 8

9 5 4

10 7 9 9 7

5 2 8 2 3

7 4 9 10 4

9 6 2 4 4

9 10 10 5 5

8 5 4 2 4

9 5 4 10 6

8 6 8 9 10

10 9 2 8 9

7 1 10

5 1 2

2 0 9

4 0 8

7 7 1

1 1 2 6 2 7 6

4 9 9 7 9 1 1

4 8 3 5 6 9 5

9 1 2 6 1 6 4

7 1 2 2 1 6 2

5 10 1 3 8 7 9

3 10 2 9 3 2 2

6 0 10

예제 출력

#1 76

#2 74

#3 49

#4 133

#5 173

 

#코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import sys
from collections import deque
 
# N개의 층에 각각 M개의 숫자가 쓰여있다
# 회전탑은 층에 존재하는 숫자를 회전시킬 수 있다.
# 회전 후 인접한 부분의 숫자가 같을 경우 회전판에서 숫자를 지운다.
 
# 회전은 시계 방향 혹은 반시계 방향으로 가능
# 한 번 회전시 회전되는 층은 다수가 될 수 있다.
# 회전시켜야할 층의 번호와 배수관계에 있는 회전판들은 모두 회전된다. 
# 어떠한 층에서도 지워지는 숫자가 없을 경우, 
# 모든 층에 존재하는 숫자들의 평균을 구해 각각의 숫자와 비교한다.(평균값의 소숫점 아래는 버린다)
# 만약 평균보다 크면 -1을, 평균보다 작으면 +1을 더해준다
# 앞서 말한 처리를 한 다음엔 다시 제거가 일어나는 것이 아닌 다음 회전이 일어난다.
 
# 회전탑의 정보와 회전시키는 정보가 주어졌을때, 회전을 마친 뒤 탑에 남아있는 숫자들의 합을 구해보자.
 
def push(frame, moveInfo): 
  a = moveInfo[0# 회전시킬 층의 번호
  d = moveInfo[1# 방향 0 : 시계방향(-1), 1 : 반시계방향(1)
  c = moveInfo[2# 회전시킬 칸 수
  
  # 1. 회전 시킨다.
  for i in range(1len(frame)+1):  
    if i%a == 0:  
      deq = deque(frame[i-1])
      # 시계 방향
      if d == 0:
        deq.rotate(c)
      # 반시계 방향
      if d == 1:
        temp = c*(-1)
        deq.rotate(temp)
      frame[i-1= deq
      
  # 2. 인접 녀석들을 지운다. 지워지는 요소들은 카운팅 하지 않도록 주의!
  # cnt를 체크해서 0인 경우 평균값을 구한다.
  # 평균보다 크면 -1을, 평균보다 작으면 +1을 더해준다
  # 상, 하, 좌, 우 비교 
  # 좌-우는 이어져 있으나, 상-하는 이어져 있지 않다.
  # 배열 복사본을 만들어 없어지는 경우를 표시
  '''
  4 3 6 1 3 
  2 6 3 2 3 
  6 5 1 9 7 
  9 8 3 8 2 
  '''
  cnt = 0
  temp_matrix = [[False]*for _ in range(n)] # 없어 졌으면 True
  # 상 하 좌 우
  dy = [-1100]
  dx = [00-11
  outline = [[-1]*(m) for _ in range(n+2)]
  
  for i in range(n):
    for j in range(m):
      outline[i+1][j] = frame[i][j]
  
  for i in range(1, n+1):
    for j in range(m): 
      
      tempTop  = dy[0+ i
      tempDown = dy[1+ i
      
      tempLeft = dx[2+ j
      if tempLeft <= -1:
        tempLeft = m-1
      tempRight = dx[3+ j
      if tempRight >= m:
        tempRight = 0
        
      if outline[i][j] == outline[tempTop][j] or outline[i][j] == outline[tempDown][j] or outline[i][j] == outline[i][tempLeft] or outline[i][j] == outline[i][tempRight]:
        if outline[i][j] != 0:
          temp_matrix[i-1][j] = True
          cnt += 1
   
  for i in range(n):
    for j in range(m):
      if temp_matrix[i][j] == True:
        frame[i][j] = 0 
  
  # 어떠한 층에서도 지워지는 숫자가 없을 경우, 
  if cnt == 0:
    avgCnt = 0
    sum    = 0
    for i in range(n):
      for j in range(m):
        if frame[i][j] != 0:
          avgCnt += 1          
          sum += frame[i][j]
    # 모든 층에 존재하는 숫자들의 평균을 구해 각각의 숫자와 비교한다.(평균값의 소숫점 아래는 버린다)  
    avg = sum//avgCnt  
    # 만약 평균보다 크면 -1을, 평균보다 작으면 +1을 더해준다
    # 앞서 말한 처리를 한 다음엔 다시 제거가 일어나는 것이 아닌 다음 회전이 일어난다.  
    for i in range(n):
      for j in range(m):
        if frame[i][j] == 0: continue
        if frame[i][j] > avg:
          frame[i][j] -= 1
        if frame[i][j] < avg:
          frame[i][j] += 1
    
  return frame
 
if __name__ == "__main__":
  input = sys.stdin.readline
  
  t = int(input())
  
  for aa in range(t): 
    n, m, k   = map(int, input().split())
    frameInfo = [list(map(int, input().split())) for _ in range(n)]
    moveInfo  = [list(map(int, input().split())) for _ in range(k)]
        
    for i in moveInfo:
      frameInfo = push(frameInfo, i)
    sum = 0
    for i in frameInfo:
      for j in i: 
        sum += j 
    print('#' + str(int(aa+1)) + ' ' + str(sum))      
   
cs

 

반응형

'CS > 알고리즘_문제풀이(파이썬)' 카테고리의 다른 글

원형큐 구현하기  (0) 2021.05.26
괄호의 값  (0) 2021.05.26
검증수  (0) 2021.05.25
car  (0) 2021.05.25
괄호  (0) 2021.05.24