STUDY/Algorithm

[백준] 20056 마법사 상어와 파이어볼 Python

sinawi95 2022. 3. 31. 11:42
728x90

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

 

20056번: 마법사 상어와 파이어볼

첫째 줄에 N, M, K가 주어진다. 둘째 줄부터 M개의 줄에 파이어볼의 정보가 한 줄에 하나씩 주어진다. 파이어볼의 정보는 다섯 정수 ri, ci, mi, si, di로 이루어져 있다. 서로 다른 두 파이어볼의 위치

www.acmicpc.net

시뮬레이션 문제이다.

알고리즘 순서는 다음과 같다.

1. 입력
1-1. board: 격자 정보, fireballs: 파이어볼 정보
1-2. 0 <= M <= N^2, N <= 50

입력할 때 격자(이차원 배열)에 여러 개의 파이어볼이 들어갈수 있으므로 리스트로 초기화했다.

2. 시뮬레이션 (K번 반복)
2-1. 모든 파이어볼 이동
2-2. 격자에 파이어볼이 있으면 행동
2-2-1. 격자에 파이어볼이 하나만 있는 경우
2-2-2. 두개 이상인 경우 

파이어볼 이동하는 건 fireballs에서 정보를 가져와 board에 추가했고, 모든 정보를 추가했으면 파이어볼이 있는 격자에서 작업을 진행했다. 파이어볼이 하나인 경우엔 그대로 fireballs에 추가했고 두개 이상인 경우에만 합쳤다. 두개 이상인 경우 합치는 작업 이후 질량이 0이 될수 있으므로 이를 확인하면서 fireballs에 추가했다.

3. 출력: 남은 파이어볼 질량의 총 합

시뮬레이션이 끝난후 fireballs에 남은 파이어볼이 있으므로 list comprehension을 사용해서 질량만 추출한 리스트를 만들고, 이를 다합친 값을 출력했다.

 

 

import sys; input = sys.stdin.readline
d = [(-1, 0), (-1, 1), (0, 1), (1, 1), (1, 0), (1, -1), (0, -1), (-1, -1)]

def main():
    # 0 input
    N, M, K = map(int, input().split())
    fireballs = []
    for _ in range(M):
        ri, ci, mi, si, di = map(int, input().split())
        ri -= 1
        ci -= 1
        fireballs.append([ri, ci, mi, si, di])
    board = [[[] for _ in range(N)] for _ in range(N)]

    # 1 simulation
    for _ in range(K):
        # 1) all fireballs move
        while fireballs:
            ri, ci, mi, si, di = fireballs.pop()
            ri = (ri + d[di][0] * si) % N
            ci = (ci + d[di][1] * si) % N
            board[ri][ci].append([mi, si, di])
        # 2) split fireballs
        for r in range(N):
            for c in range(N):
                if not board[r][c]:
                    continue
                # if len(board[r][c]) >= 1, calculate n
                sum_m, sum_s, sum_num = 0, 0, len(board[r][c])
                tmp_d = []
                while board[r][c]:
                    mi, si, di = board[r][c].pop()
                    sum_m += mi
                    sum_s += si
                    tmp_d.append(di % 2)
                if sum_num > 1:
                    sum_m //= 5
                    sum_s //= sum_num
                    tmp_sum = sum(tmp_d)
                    if tmp_sum == 0 or tmp_sum == sum_num:
                        tmp_d = [0, 2, 4, 6]
                    else:
                        tmp_d = [1, 3, 5, 7]
                else: # sum_num == 1
                    tmp_d = [di]
                # Add fireball in fireballs
                if sum_m:
                    for td in tmp_d:
                        fireballs.append([r, c, sum_m, sum_s, td])
    # 2 output
    answer = sum([m for _, _, m, _, _ in fireballs])
    print(answer)



if __name__ == "__main__":
    main()