코딩테스트/구현
마법사 상어와 비바라기
수타.
2023. 8. 11. 16:07
https://www.acmicpc.net/problem/21610
21610번: 마법사 상어와 비바라기
마법사 상어는 파이어볼, 토네이도, 파이어스톰, 물복사버그 마법을 할 수 있다. 오늘 새로 배운 마법은 비바라기이다. 비바라기를 시전하면 하늘에 비구름을 만들 수 있다. 오늘은 비바라기
www.acmicpc.net
문제요약:
n*n 바구니의 물의양이 주어지고
- 모든 구름이 di 방향으로 si칸 이동한다.
- 각 구름에서 비가 내려 구름이 있는 칸의 바구니에 저장된 물의 양이 1 증가한다.
- 구름이 모두 사라진다.
- 2에서 물이 증가한 칸 (r, c)에 물복사버그 마법을 시전한다. 물복사버그 마법을 사용하면, 대각선 방향으로 거리가 1인 칸에 물이 있는 바구니의 수만큼 (r, c)에 있는 바구니의 물이 양이 증가한다.
- 이때는 이동과 다르게 경계를 넘어가는 칸은 대각선 방향으로 거리가 1인 칸이 아니다.
- 예를 들어, (N, 2)에서 인접한 대각선 칸은 (N-1, 1), (N-1, 3)이고, (N, N)에서 인접한 대각선 칸은 (N-1, N-1)뿐이다.
- 바구니에 저장된 물의 양이 2 이상인 모든 칸에 구름이 생기고, 물의 양이 2 줄어든다. 이때 구름이 생기는 칸은 3에서 구름이 사라진 칸이 아니어야 한다.
다음과 같은 기준에 따라 물의양이 이동할 때, 이동이 모두 끝난 후 바구니에 들어있는 물의 양의 합을 출력하라
소요시간:
35분
난이도 :
골드5
제출횟수:
1번
코딩:
import sys
input = sys.stdin.readline
n,m = map(int,input().split())
arr = [list(map(int,input().split())) for _ in range(n)]
ds = [list(map(int,input().split())) for _ in range(m)]
cloud = [[-1,0],[-1,1],[-2,0],[-2,1]]
dy = [0,-1,-1,-1,0,1,1,1]
dx = [-1,-1,0,1,1,1,0,-1]
def fix(x):
while x<0:
x+=n
while x>=n:
x-=n
return x
for d,s in ds:
water = []
#모든 구름이 이동한다
for y,x in cloud:
ny = fix(y+s*dy[d-1])
nx = fix(x+s*dx[d-1])
#저장된물 증가
arr[ny][nx] +=1
#물이 증가한 칸 저장
water.append([ny,nx])
#구름 초기화
cloud = []
#대각선에 물 확인후 증가
for y,x in water:
for i in range(1,8,2):
ny = y+dy[i]
nx = x+dx[i]
if 0<=ny<n and 0<=nx<n:
if arr[ny][nx]:
arr[y][x]+=1
#내부 판단을 위해 set으로 변경
water = set([n*y+x for y,x in water])
for y in range(n):
for x in range(n):
if n*y+x not in water and arr[y][x] >=2:
cloud.append([y,x])
arr[y][x]-=2
print(sum([i for j in arr for i in j]))
차근차근 문제에서 주어진 규칙을 따라가면 되는 구현 문제였습니다. 구름이 이동할때 벽에 끝에 다다르면 맞은편으로 넘어가기 때문에 fix함수를 통해 이를 바꿔주었고, 마지막에 구름이 있었던 곳 제외하고 다시 구름을 설정할때 비교의 편의를 위해 set함수를 통해 1차원으로 바꿔주어 비교를 했습니다.