코딩테스트/구현
마법사 상어와 파이어
수타.
2023. 8. 2. 11:56
https://www.acmicpc.net/problem/20056
20056번: 마법사 상어와 파이어볼
첫째 줄에 N, M, K가 주어진다. 둘째 줄부터 M개의 줄에 파이어볼의 정보가 한 줄에 하나씩 주어진다. 파이어볼의 정보는 다섯 정수 ri, ci, mi, si, di로 이루어져 있다. 서로 다른 두 파이어볼의 위치
www.acmicpc.net
문제요약:
마법사 상어가 특정조건을 따르는 파이어볼에게 이동하라고 명령했을때,
마법사 상어가 이동을 k번 명령한 후, 남아잉ㅆ는 파이어볼 질량의 합을 구해보자.
소요시간:
45분
난이도:
골드4
제출횟수:
1번
코딩:
import sys
input = sys.stdin.readline
from collections import defaultdict
N,M,K = map(int,input().split())
arr = defaultdict(list)
dy = [-1,-1,0,1,1,1,0,-1]
dx = [0,1,1,1,0,-1,-1,-1]
for _ in range(M):
r,c,m,s,d = map(int,input().split())
arr[(r-1)*N + (c-1)].append([m,s,d])
for _ in range(K):
temp = defaultdict(list)
#이동
for y in range(N):
for x in range(N):
if arr[y*N+x] :
for m,s,d in arr[y*N+x]:
ny = y+dy[d]*s
nx = x+dx[d]*s
#넘어가면, 원래대로 돌려준다
while ny>=N:
ny-=N
while ny<0:
ny+=N
while nx>=N:
nx-=N
while nx<0:
nx+=N
temp[ny*N + nx].append([m,s,d])
#겹치는게 있다면, 조건에 맞게 분리시켜주기
for y in range(N):
for x in range(N):
if len(temp[y*N+x])>=2:
m,s,d= zip(*temp[y*N+x])
m = sum(m)//5
if m==0:
temp[y*N+x] = []
continue
s = sum(s)//len(temp[y*N+x])
piv =1
#모두짝수거나 모두 홀수라면
if all([i%2 for i in d]) or not any([i%2 for i in d]):
piv =0
#초기화하고
temp[y*N+x] = []
for dir in range(0,7,2):
temp[y*N+x].append([m,s,dir+piv])
arr = temp
ans = 0
for y in range(N):
for x in range(N):
if arr[y*N+x]:
if len(arr[y*N+x])==1:
ans += arr[y*N+x][0][0]
else:
m,s,d= zip(*temp[y*N+x])
ans += sum(m)
print(ans)
이번 문제 역시 구현 문제기 때문에, 알고리즘을 알아야 하진 않았다. 하지만 defaultdict이나 all, any,zip등 함수들을 통해 조금더 간결하게 문제를 구현할 수 있었다.
시간을 끈 부분이 m,s,d를 따로 추출할때 zip(*temp)를 사용했다.
만약 [[1,2,3],[4,5,6]]이temp라면 zip(*)함수를 사용하면 [(1,4),(2,5),(3,6)] 과 같이 열을 추출할 수 있는데, 각열을 추출하기 위해 for m,s,d in zip(*temp)를 사용했어서 오류가 있었다 이렇게 하면, m에 (1,4) s에 (2,5) d에(3,6)이 아닌 m에 1 s에 4가 할당되고 d에 할당될것이 없어서 오류가 뜨게된다. m,s,d = zip(*temp)와같이 해야 원하는데로 할당할 수 있다.