꾸준하게 거북이처럼

백준 마법사상어와 파이어볼 파이썬 본문

Algorithm 문제 & 공부/구현

백준 마법사상어와 파이어볼 파이썬

somm12 2023. 7. 30. 14:45

 

 

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

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

www.acmicpc.net

이런 유형의 문제는 시뮬레이션 + 구현 문제로,

한 좌표에서 여러개의 정보가 들어가는데, 보통 dictionary나 2차원 배열을 사용한다.

아래와 같이 dictionary를 써보니 코드가 생각보다 간략해졌다.

1. 조건

- m개의 파이어볼, 방향 8방향, 처음 끝 행과 처음 끝 열 연결되어있음.
- d방향 s칸 이동, 명령 k번
- 2개이상 파이어볼이 있으면 같은 파이어볼 4개로 나누어짐.(모두 방향이 짝/홀수면 0,2,4,6 아니면 1,3,5,7)
- 질량은 질량합//5, 속력은 솔력합// 파이어볼개수
- 질량이 0이면 소멸됨.

2. 설계

크게 시뮬레이션을 보면 k번 동안 볼이 모두 움직이고, 그다음 합쳐서 4개로 나눠진다.

함수 2개로 나누어 구현해본다. ex) move, makeOne

3. 코드

from collections import defaultdict
answer = 0
ball = defaultdict(list)
n,m,k = map(int,input().split())
dx =[-1,-1,0,1,1,1,0,-1] # 8가지 방향.
dy = [0,1,1,1,0,-1,-1,-1]
def move():# 파이어볼 모두 이동.
    global ball
    new = defaultdict(list)
    for x,y in ball: 
        for m,s,d in ball[(x,y)]:
            nx = (x+dx[d]*s) # d방향 s칸.
            ny = (y+dy[d]*s) 
            nx %= n # 행 열 모두 연결 됨.
            ny %= n
            new[(nx,ny)].append([m,s,d]) # 옮겨진 위치로 다시 할당.
    ball =new # ball 위치 update.
 
def makeOne():# 2개이상 한칸에 있는 파이어볼 하나로 합치기.
    global ball

    for x,y in ball:
        if len(ball[(x,y)]) >= 2:
            length = len(ball[(x,y)])
            totalM, totalS, even, odd = 0,0,0,0 # 총질량, 속력, 방향이 짝수 홀수인지 확인 위한 변수.
            for m,s,d in ball[(x,y)]:
                totalM += m
                totalS += s

                if d % 2 == 0:
                    even += 1
                else:
                    odd += 1
            if totalM // 5 == 0:# 질량이 0 이면 소멸. del를 쓰면 for반복문에서 ball 이 바뀌므로, 조심.
                ball[(x,y)] = []
                continue
            else:
                ball[(x,y)] = []# 만약 모두 방향이 짝수 또는 홀수라면 0,2,4,6 방향으로 할당.
                if even == length or odd == length:
                    for i in [0,2,4,6]:
                        ball[(x,y)].append([totalM//5, totalS//length,i])
                else:
                    for i in [1,3,5,7]:
                        ball[(x,y)].append([totalM//5, totalS//length,i])
for _ in range(m):# m개 입력
    r,c,m,s,d = map(int,input().split())
    ball[(r-1,c-1)].append([m,s,d])

for _ in range(k):# K번 마법.

    move()
    makeOne()

for x,y in ball:# 총질량합 구하기.
    for m,s,d in ball[(x,y)]:
        answer += m
print(answer)
Comments