성장기록지

백준 20056 마법사 상어와 파이어볼 (python) 본문

알고리즘/구현

백준 20056 마법사 상어와 파이어볼 (python)

pengcon 2025. 2. 2. 16:05

문제

풀이

이 코드는 파이어볼을 이동시키고, 충돌 시 합쳐지는 로직을 구현한 시뮬레이션 문제다.

기본적으로 arr이라는 2차원 리스트를 사용해 각 좌표에 있는 파이어볼 정보를 저장한다. 초기에는 파이어볼의 위치와 정보를 입력받아 fireballs 리스트에 저장하고, 이후 K번의 이동을 수행한다.

  1. 파이어볼 이동
    각 파이어볼을 현재 위치에서 방향과 속력에 따라 이동시킨다. 격자를 벗어나지 않도록 N으로 나눈 나머지를 이용해 위치를 조정한다.
  2. 이동한 파이어볼을 다시 저장
    이동이 끝난 후, 새로운 위치에 파이어볼 정보를 저장한다.
  3. 파이어볼 합치기
    같은 위치에 여러 개의 파이어볼이 모이면,
    • 질량과 속력을 합산하여 새로운 파이어볼을 만든다.
    • 원래 방향이 모두 홀수이거나 모두 짝수이면 [0, 2, 4, 6] 방향으로 나누고, 그렇지 않으면 [1, 3, 5, 7]로 나눈다.
    • 질량이 0이면 사라지므로 추가하지 않는다.
  4. 남아있는 파이어볼의 질량 합 출력
    마지막에 남은 파이어볼의 질량을 모두 더해 출력한다.

코드

N, M, K = map(int, input().split())
# 파이어볼의 리스트
arr = [[[] for _ in range(N)] for _ in range(N)] 
# 파이어볼 위치 리스트
fireballs=[]
# 0~8
dx=[-1, -1, 0, 1, 1, 1, 0, -1]
dy=[0, 1, 1, 1, 0, -1, -1, -1]
even_direction = [0,2,4,6]
odd_direction = [1,3,5,7]
ans = 0
#처음 파이어볼 입력
for _ in range(M):
    # 행,열,질량,속력,방향
    r, c, m, s, d = list(map(int, input().split()))
    arr[r-1][c-1].append([m,s,d])
    fireballs.append([r-1,c-1])
#이동 횟수만큼
for _ in range(K):
    moved_fireball=[]
    # 파이어볼 이동
    for x,y in fireballs:
        m,s,d = arr[x][y].pop()
        nx = (x + dx[d] * s) % N
        ny = (y + dy[d] * s) % N
        moved_fireball.append([nx, ny, m, s, d])
    fireballs=[]
    #이동한 파이어볼 arr에 넣어줌
    for mx, my, m, s, d in moved_fireball:
        arr[mx][my].append([m,s,d])
    # 2개 이상이면 파이어볼 합치기
    for i in range(N):
        for j in range(N):
            # 한칸에 하나 있으면
            if len(arr[i][j]) == 1:
                fireballs.append([i,j])
            # 한 칸에 파이어볼 2개 이상 있으면
            if len(arr[i][j])>=2:
                sum_len=len(arr[i][j])
                sum_m = 0
                sum_s = 0
                even = False
                odd = False
                for _ in range(len(arr[i][j])):
                    m, s, d = arr[i][j].pop()
                    sum_m += m
                    sum_s += s
                    # 방향 홀짝 확인
                    if d%2 ==0:
                        even = True
                    else:
                        odd = True
                
                div_m = sum_m // 5
                div_s = sum_s // sum_len
                # 질량이 0 이면 걍 소멸,
                # 0 이상이면 추가
                if div_m>0:
                    if even == False or odd == False:
                        for d in even_direction:
                            arr[i][j].append([div_m,div_s,d])
                            fireballs.append([i,j])
                    else:
                        for d in odd_direction:
                            arr[i][j].append([div_m,div_s,d])    
                            fireballs.append([i,j])  
       
for i in range(N):
    for j in range(N):
        for k in arr[i][j]:
            ans += k[0]
print(ans)