알고리즘 문제 풀이/Python

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

맛대 2024. 11. 18. 21:34

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

로직

  • 구현문제
  • 파이어볼 이동과 파이어볼 병합 두가지로 구성된 문제
  • 격자의 시작과 끝이 연결되어 있으므로 나머지 연산 활용(%N)
  • 2개 이상 파이어볼이 있는 칸을 확인하기 위해 N*N 크기의 배열 사용(변수명 arr)
  • 파이어볼이 병합되는 경우 방향 계산을 위해 비트연산 사용
    • (방향%2) 계산시 짝수, 홀수에 따라 0과 1의 값이 나옴
    • 여기에 1을 더하면 짝수는 1, 홀수는 2의 값
    • 방향(변수명 diretion)을 이 값과 AND연산
    • 모두 홀수 방향인 경우 값은 2, 모두 짝수 방향인 경우 값은 1, 홀짝 모두 있을 경우 값이 3이 되는 것을 활용

실수했던 것

  • 입력값이 주어질 때 부터 스피드를 격자크기로 나머지 연산을 해버렸는데, 이 경우 파이어볼 병합 시 스피드 몫 연산에서 차이가 발생
from collections import deque
import sys
input = sys.stdin.readline
dr,dc = (-1,-1,0,1,1,1,0,-1),(0,1,1,1,0,-1,-1,-1)
N,M,K = map(int,input().split())
fireBalls = deque()
for _ in range(M):
    r,c,m,s,d = map(int,input().split())
    fireBalls.append((r-1,c-1,m,s,d))

arr = [[[] for _ in range(N)] for __ in range(N)]
for cnt in range(K):
    # 파이어볼 이동
    for i in range(len(fireBalls)):
        r,c,m,s,d = fireBalls.popleft()
        nr,nc = (r+s*dr[d])%N, (c+s*dc[d])%N
        arr[nr][nc].append((m,s,d))

    # 파이어볼 병합
    for r in range(N):
        for c in range(N):
            if len(arr[r][c]) > 1:
                mass,speed,direction = 0,0,0
                for m,s,d in arr[r][c]:
                    mass += m
                    speed += s
                    direction |= (d%2)+1
                mass //= 5
                speed //= len(arr[r][c])
                arr[r][c].clear()
                if mass != 0:
                    start = 1 if direction == 3 else 0
                    for d in range(start,8,2):
                        arr[r][c].append((mass,speed,d))
            for m,s,d in arr[r][c]:
                fireBalls.append((r,c,m,s,d))
            arr[r][c].clear()
ans = 0
for fireBall in fireBalls:
    mass = fireBall[2]
    ans += mass
print(ans)