본문 바로가기
Problem Solving/BOJ

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

by 부르르 2021. 4. 24.

www.acmicpc.net/problem/20056

 

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

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

www.acmicpc.net


 

Point

  • 첫 입력에서 서로 다른 두 파이어볼 위치가 같은 경우는 없음
  • 파이어볼 질량이 0 이 되면 소멸

 

 

 

Tip

  • 2차원 리스트 배열을 선언하여 이동이 끝난 뒤 파이어볼 합치기/분열을 연산
  • 파이어볼의 방향을 연산할 때, 총합이 짝수/홀수냐로 모두 짝수/홀수인지 아닌지를 판별하면 안된다.
    짝짝홀홀일 때 총합은 짝수이기 때문이다. 

 

메모리 (제한: 512MB)

138280 KB

시간 (제한: 1초)

488 ms

결과

100%

 

import sys
input = sys.stdin.readline

n,m,k = map(int, input().split())
fireballs = []
for _ in range(m):
    _r,_c,_m,_s,_d = map(int, input().split())
    fireballs.append([_r-1,_c-1,_m,_s,_d])
dydx = [[-1,0],[-1,1],[0,1],[1,1],[1,0],[1,-1],[0,-1],[-1,-1]]

for _ in range(k):
    MAP = [[[] for _ in range(n)] for _ in range(n)]

    # 모든 파이어볼 이동
    while fireballs:
        cy,cx,cm,cs,cd = fireballs.pop(0)
        ny = (cy + cs*dydx[cd][0])%n
        nx = (cx + cs*dydx[cd][1])%n
        MAP[ny][nx].append([cm,cs,cd])

    # 이동이 끝난 뒤 2개 이상칸에서는 합치고 분열
    tmp = []
    for r in range(n):
        for c in range(n):
            if MAP[r][c]:
                if len(MAP[r][c]) == 1:
                    tmp.append([r,c]+MAP[r][c][0])
                    # answer += MAP[r][c][0][0]
                else:
                    cnt = len(MAP[r][c])
                    sum_m = 0
                    sum_s = 0
                    cnt_odd = 0
                    cnt_even = 0
                    while MAP[r][c]:
                        _m,_s,_d = MAP[r][c].pop(0)
                        sum_m += _m
                        sum_s += _s
                        if _d % 2 == 1:
                            cnt_odd += 1
                        else:
                            cnt_even += 1

                    # 짝 짝 홀 홀 이어도 합이 양수가 나올 수 있음
                    # 방향이 모두 양수/음수인지 판별
                    flag = False
                    if cnt_odd == cnt or cnt_even == cnt:
                        flag = True

                    if sum_m//5 > 0:
                        if flag:
                            for nd in [0,2,4,6]:
                                tmp.append([r,c,sum_m//5,sum_s//cnt,nd])
                        elif not flag:
                            for nd in [1,3,5,7]:
                                tmp.append([r,c,sum_m//5,sum_s//cnt,nd])
                        # answer += (sum_m//5)*4
                    # 질량이 0 인 파이어볼은 소멸
                    else:
                        continue
    fireballs = tmp

answer = sum([f[2] for f in fireballs])
print(answer)

 

문제를 푸는데 도움이 된 테스트 케이스

 

 

728x90
반응형

댓글