본문 바로가기

백준 파이썬 코딩

백준 17822 원판 돌리기 파이썬

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

 

17822번: 원판 돌리기

반지름이 1, 2, ..., N인 원판이 크기가 작아지는 순으로 바닥에 놓여있고, 원판의 중심은 모두 같다. 원판의 반지름이 i이면, 그 원판을 i번째 원판이라고 한다. 각각의 원판에는 M개의 정수가 적혀

www.acmicpc.net

*중요한 포인트*

1. 바로 deque를 떠올리는 것 (방향에따라 appendleft(pop()) // append(popleft()))해주기 위해

2. x 배수의 원판만 돌아간다는 것.

3. 숫자 삭제와 증감은 모든 원판이 다 돌아가고 일어난다는 것 (제일 중요)

4. 원판 안의 모든 숫자가 0일 수 있다.(런타입 에러 관련)

 

코드 설명은 코드 주석으로 하겠습니다. 

from collections import deque
import sys

def move(x,d,k):
    for i in range(x,n+1,x):#x의 배수의 원판을 돌려주는 작업이다.
        for _ in range(k):
            if d==1:
                s[i-1].append((s[i-1].popleft()))
            else:
                s[i-1].appendleft((s[i-1].pop()))
    de = set()#지울 idx번호를 저장해줄 set<-(list로 해주면 중복되는 경우가 많아 지울때 시간초과 우려가 있음.)
    for i in range(1,n+1):
    #지운 수는 0으로 해줄 것이므로 0==0은 제외.
        if 1<i<n:#원판이 맨 끝이나 안이 아니면 안, 밖 원판을 비교해야한다.
            for j in range(m):
                if s[i-1][j-1]==s[i-1][j] and s[i-1][j]!=0:# 원판내에서 비교
                    de.add((i-1,j))
                    de.add((i-1,j-1))
                if s[i-1][j]==s[i-2][j] and s[i-1][j]!=0:#인접한 안의 원판과 비교
                    de.add((i-1,j))
                    de.add((i-2,j))
                if s[i-1][j]==s[i][j] and s[i-1][j]!=0:#인접한 밖의 원판과 비교
                    de.add((i-1,j))
                    de.add((i,j))
        elif i==n:
            for j in range(m):
                if s[i-1][j-1]==s[i-1][j] and s[i-1][j]!=0:# 원판내에서 비교
                    de.add((i-1,j))
                    de.add((i-1,j-1))
                if s[i-1][j]==s[i-2][j] and s[i-1][j]!=0:#인접한 안의 원판과 비교
                    de.add((i-1,j))
                    de.add((i-2,j))
        elif i==1:
            for j in range(m):
                
                if s[i-1][j-1]==s[i-1][j] and s[i-1][j]!=0:# 원판내에서 비교
                    de.add((i-1,j))
                    de.add((i-1,j-1))
                if s[i-1][j]==s[i][j] and s[i-1][j]!=0:#인접한 밖의 원판과 비교
                    de.add((i-1,j))
                    de.add((i,j))
        
    if de!=set():#지울 것이 존재하면 지워준다.
            for i,j in de:
                s[i][j]=0
    else:#존재하지 않으므로 0이 아닌 숫자들의 합을 구하고 문제에서 말한대로 해준다.
            sums=0
            d=[]#idx저장
            for q in range(n):#완전 탐색을 통해 0이 아닌 수를 찾음.
                for w in range(m):
                    if s[q][w]!=0:
                        sums+=s[q][w]
                        d.append((q,w))
            if d!=[]:#0이 아닌 수가 있는 경우다.  (이걸 안 해주면 런타입 에러가 난다. 0/0이 됨.)
                mean = sums/len(d)#int형으로 해주면 안 됨.
                for q,w in d:
                    if s[q][w]>mean:#평균보다 크면 -1
                        s[q][w]-=1
                    elif s[q][w]<mean:#평균보다 작으면 +1
                        s[q][w]+=1
input = sys.stdin.readline
n,m,t = map(int,input().split())
s = deque()
for _ in range(n):
    s.append(deque(map(int,input().split())))

for _ in range(t):
    x,d,k = map(int,input().split())
    move(x,d,k)
sums=0
for i in s:
    sums+=sum(i)
print(sums)