본문 바로가기
알고리즘/삼성

[백준-골드5] 21610번 마법사 상어와 비바라기(구현, 파이썬)

by 호리미 2022. 2. 10.

https://www.acmicpc.net/problem/21610

 

21610번: 마법사 상어와 비바라기

마법사 상어는 파이어볼, 토네이도, 파이어스톰, 물복사버그 마법을 할 수 있다. 오늘 새로 배운 마법은 비바라기이다. 비바라기를 시전하면 하늘에 비구름을 만들 수 있다. 오늘은 비바라기

www.acmicpc.net

 

<내 코드>

- 우선 방향을 문제에서 제시한대로 8가지 방향으로 설정하였다.

- 구름이 이동을 담기위해 move_cloud 리스트를 초기화하고  반복문을 돌면서 구름이 있을 때 이동한다.

- dx[d-1]*s 만큼 이동하는데 문제에서 1행과 n행, 1열과 n열이 연결되어있다고 했으므로 그때 nx,ny 의 예외처리 해줌

- 구름이 이동하면 move_cloud에 True처리하고 구름에서 비가 내려 칸에 저장된 물이 1 증가한다.

- 이 때, move_cloud를 이용한 이유는 colud를 사용하면 이동한 곳이 True가 되므로 확인할때 중복이 발생하기 때문

- 그 후 물복사 버그를 실행한다. 내가 설정한 dx, dy에서 대각선은 1,3,5,7이다.

- nx,ny가 범위에 들어오고 물이 있을때(이 범위를 체크 안해서 틀렸었음)

- 대각선 범위 4개를 돌면서 조건에 해당되면 물을 하나씩 늘려준다.

- 구름이 없고 물이 2이상인 곳에 구름이 생기고, 물이 줄어들고, 원래 구름이 있던 곳은 False처리해준다.

- 최종적으로 명령이 다 수행되면 칸에 있는 물의 수를 세어준다.

 

import sys

# 입력
n, m = map(int, sys.stdin.readline().split())
a = []
for _ in range(n):
    a.append(list(map(int, sys.stdin.readline().split())))

command = []  # 방향, 거리
for _ in range(m):
    command.append(list(map(int, sys.stdin.readline().split())))

cloud = [[False] * n for _ in range(n)]


# 비바라기 시전
cloud[n - 1][0] = True
cloud[n - 1][1] = True
cloud[n - 2][0] = True
cloud[n - 2][1] = True

dx = [0, -1, -1, -1, 0, 1, 1, 1]
dy = [-1, -1, 0, 1, 1, 1, 0, -1]
for com in command:
    # 구름 이동
    d, s = com[0], com[1]
    move_cloud = [[False] * n for _ in range(n)]
    for i in range(n):
        for j in range(n):
            if cloud[i][j]:  # 구름이 있다면
                # 명령 방향으로, 명령 거리만큼 이동
                nx = i + dx[d - 1] * s
                ny = j + dy[d - 1] * s
                # 0행, n행, 0열, n열 연결 되어있으므로 예외 처리
                if nx >= n or nx < 0:
                    nx = (n+nx) % n

                if ny >= n or ny < 0:
                    ny = (n+ny) % n

                move_cloud[nx][ny] = True  # 구름 이동
                a[nx][ny] += 1  # 각 구름에서 비가 내려서 저장된 물 1 증가

    cloud = move_cloud[:][:] #복사
    # 물복사버그 마법 시전
    for i in range(n):
        for j in range(n):
            if cloud[i][j] == True:
                for k in [1, 3, 5, 7]:  # dx, dy에서 대각선방향
                    nx = i + dx[k]
                    ny = j + dy[k]
                    if 0 <= nx < n and 0 <= ny < n and a[nx][ny]>0:  # 범위 안에 있으면
                        a[i][j] += 1
                        
    # 구름이 없고, 물이 2 이상이면 구름이 생기고, 물이 줄어든다
    # 이 때 원래 구름이 있던 곳은 False 처리해준다.
    for i in range(n):
        for j in range(n):
            if cloud[i][j]== False and a[i][j]>=2:
                a[i][j]-=2# 물 줄어듦
                cloud[i][j] = True #구름 생김
            elif cloud[i][j] == True:
                cloud[i][j] = False


result = 0
for i in range(n):
    for j in range(n):
        result += a[i][j]

print(result)