# 마법사 상어와 파이어볼
import sys
input = sys.stdin.readline
dx = [-1, -1, 0, 1, 1, 1, 0, -1]
dy = [0, 1, 1, 1, 0, -1, -1, -1]
N, M, K = map(int, input().split())
fireball_info = []
for _ in range(M):
x, y, big, speed, dir = map(int, input().split())
fireball_info.append([x, y, big, speed, dir])
def fireball_move():
# fireball의 좌표를 집합으로 관리 (중복값없게)
fireballs = set()
# 각 위치별 fireball 표시
temp = [[[] for _ in range(N+1)] for _ in range(N+1)]
for _ in range(len(fireball_info)):
x, y, big, speed, dir = fireball_info.pop()
nx = x + dx[dir] * speed
ny = y + dy[dir] * speed
# 적절한 fireball 위치 반환
nx, ny = move_place(nx, ny)
# 이동한 좌표를 fireballs 집합에 추가
fireballs.add((nx, ny))
# temp의 해당 위치에 fireball 정보 추가
temp[nx][ny].append((big, speed, dir))
# 위치별 fireball개수 파악
fireball_spread(fireballs, temp)
def move_place(x, y):
if 1 <= x <= N and 1 <= y <= N:
return x, y
if x > N:
x = x % N
if x < 1:
x = N-abs(x) % N
if y > N:
y = y % N
if y < 1:
y = N-abs(y) % N
return x, y
def fireball_spread(fireballs, temp):
# 모든 fireball의 위치마다 실시
for x, y in fireballs:
# 파이어볼이 한개이면 fireball_info에 추가
if len(temp[x][y]) == 1:
big, speed, dir = temp[x][y].pop()
fireball_info.append([x, y, big, speed, dir])
continue
# 파이어볼이 2개 이상이면
leng = len(temp[x][y])
sum_big, sum_speed, dirs = 0, 0, []
while temp[x][y]:
big, speed, dir = temp[x][y].pop()
sum_big += big
sum_speed += speed
dirs.append(dir)
# 새로운 질량
new_big = sum_big // 5
# 만약 질량이 0이면 파이어볼 소멸
if new_big == 0:
continue
# 새로운 스피드
new_speed = sum_speed // leng
# 새로운 방향 결정
even, odd = 0, 0
isOK = True
for d in dirs:
if d % 2 == 0:
even += 1
else:
odd += 1
if even and odd:
isOK = False
break
# 모두 짝수이거나 홀수이면
if isOK:
for nd in [0, 2, 4, 6]:
fireball_info.append((x, y, new_big, new_speed, nd))
# 아니라면
else:
for nd in [1, 3, 5, 7]:
fireball_info.append((x, y, new_big, new_speed, nd))
for _ in range(K):
fireball_move()
result = 0
for _, _, big, _, _ in fireball_info:
result += big
print(result)
구현(시물레이션)
1. fireball_info 리스트에 파이어볼의 정보를 입력받는다
2. K번 fireball_move 진행
- fireballs : 파이어볼들이 존재하는 모든 좌표를 관리, temp : 각 좌표마다 fireball의 정보를 표시
- move_place : 적절한 이동 위치를 반환
- fireball_spread : fireballs와 temp를 이용해서 fireball이 합쳐지고 퍼져나가는 기능을 실행
3. 남은 fireball_info의 크기를 모두 더해서 출력
이전에 풀었던 문제와 이어지는 스토리가 있는 문제이다.
[백준] 16236번 - 아기 상어
[백준] 19236번 - 청소년 상어
[백준] 19237번 - 어른 상어
'Algorithm > BOJ' 카테고리의 다른 글
[백준] 1941번 - 소문난 칠공주 (파이썬) (0) | 2022.03.22 |
---|---|
[백준] 6087번 - 레이저 통신 (파이썬) (0) | 2022.03.21 |
[백준] 19237번 - 어른 상어 (파이썬) (0) | 2022.03.19 |
[백준] 17852번 - 주사위 윷놀이 (파이썬) (0) | 2022.03.18 |
[백준] 20040번 - 사이클 게임 (파이썬) (0) | 2022.03.16 |