[ BOJ / Python ] 20056번 마법사 상어와 파이어볼

황승환·2022년 4월 25일
0

Python

목록 보기
280/498


이번 문제는 삼성 기출 문제로, 시뮬레이션을 구현하는 문제였다. 파이어볼의 좌표가 범위를 벗어나면 어떻게 되는지에 대한 명시가 되어있지 않아 이 부분에 대해서만 질문 검색을 통해 순환한다는 것을 알아냈다. 파이어볼의 저장 방법은 인접 행렬에 값을 갱신하는 형태로 하였다. 시뮬레이션 문제이므로 각 기능에 대한 함수를 구현하였다.

  • move(y, x, fireball)
    파이어볼의 이동 후 위치를 임시 파이어볼 리스트에 갱신한다.
  • sum_divide(y, x)
    현재 위치의 파이어볼 갯수가 2개 이상일 경우에 파이어볼을 모두 합쳐 4개의 파이어볼을 생성한다.

move함수는 fireballs리스트를 순회하며 파이어볼이 존재할 때마다 호출하게 되고, 한번의 fireballs리스트 순회가 끝나면 sum_divide함수를 통해 파이어볼을 합치고 나누게 된다.

처음에 실수한 점은 파이어볼의 이동이 동시에 발생하는 것이므로 임시 리스트를 사용해야 했는데 이 부분을 놓쳐 하나의 파이어볼이 여러번 움직이게 되었다는 점이었다. 다른 실수로는 dy, dx방향을 주어진것과 반대로 구현하여 30분동안 삽질을 했다 ㅎ..

이러한 부분들을 수정하여 문제를 해결할 수 있었다.

Code

from copy import deepcopy
n, m, k=map(int, input().split())
fireballs=[[[] for _ in range(n)] for _ in range(n)]
for _ in range(m):
    r, c, mm, s, d=map(int, input().split())
    fireballs[r-1][c-1].append((mm, s, d))
dy, dx=[-1, -1, 0, 1, 1, 1, 0, -1], [0, 1, 1, 1, 0, -1, -1, -1]
def move(y, x, fireball):
    mi, si, di=fireball
    ny, nx=(y+si*dy[di])%n, (x+si*dx[di])%n
    tmp_fireballs[ny][nx].append((mi, si, di))
def sum_divide(y, x):
    s_m=0
    s_s=0
    ds=[]
    for i in range(len(fireballs[y][x])):
        s_m+=fireballs[y][x][i][0]
        s_s+=fireballs[y][x][i][1]
        ds.append(fireballs[y][x][i][2])
    s_m//=5
    s_s//=len(fireballs[y][x])
    fireballs[y][x]=[]
    if s_m==0:
        return
    odd, even=0, 0
    for d in ds:
        if d%2==0:
            even+=1
        else:
            odd+=1
    if odd==len(ds) or even==len(ds):
        for i in range(4):
            fireballs[y][x].append((s_m, s_s, 2*i))
    else:
        for i in range(4):
            fireballs[y][x].append((s_m, s_s, 2*i+1))
for _ in range(k):
    tmp_fireballs = [[[] for _ in range(n)] for _ in range(n)]
    for i in range(n):
        for j in range(n):
            if fireballs[i][j]:
                for l in range(len(fireballs[i][j])):
                    move(i, j, fireballs[i][j][l])
    fireballs=deepcopy(tmp_fireballs)
    for i in range(n):
        for j in range(n):
            if len(fireballs[i][j])>=2:
                sum_divide(i, j)
answer=0
for i in range(n):
    for j in range(n):
        if fireballs[i][j]:
            for l in range(len(fireballs[i][j])):
                answer+=fireballs[i][j][l][0]
print(answer)

profile
꾸준함을 꿈꾸는 SW 전공 학부생의 개발 일기

0개의 댓글