STUDY/Algorithm

[백준] 20057 마법사 상어와 토네이도 python

sinawi95 2021. 7. 20. 22:26
728x90

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

 

20057번: 마법사 상어와 토네이도

마법사 상어가 토네이도를 배웠고, 오늘은 토네이도를 크기가 N×N인 격자로 나누어진 모래밭에서 연습하려고 한다. 위치 (r, c)는 격자의 r행 c열을 의미하고, A[r][c]는 (r, c)에 있는 모래의 양을

www.acmicpc.net

import sys; input = sys.stdin.readline

def sand_move(pos, direction_ind, matrix):
    rate = [2, 10, 7, 1, 5, 10, 7, 1, 2]
    sand_matrix = [
                   [(-2, 0), (-1, -1), (-1, 0), (-1, 1), (0, -2), (1, -1), (1, 0), (1, 1), (2, 0)],
                   [(0, -2), (1, -1), (0, -1), (-1, -1), (2, 0), (1, 1), (0, 1), (-1, 1), (0, 2)]
                   ]
    ret = 0
    y = matrix[pos[0]][pos[1]]
    matrix[pos[0]][pos[1]] = 0
    alpha = y
    for idx, pos_tmp in enumerate(sand_matrix[direction_ind % 2]):
        r = pos[0] + pos_tmp[0] * (-1) ** (direction_ind // 2)
        c = pos[1] + pos_tmp[1] * (-1) ** (direction_ind // 2)
        val_tmp = (y * rate[idx]) // 100
        if val_tmp:
            alpha -= val_tmp
            if 0 <= r < N and 0 <= c < N:
                matrix[r][c] += val_tmp
            else:
                ret += val_tmp
    r = pos[0] + direction[direction_ind][0]
    c = pos[1] + direction[direction_ind][1]
    if 0 <= r < N and 0 <= c < N:
        matrix[r][c] += alpha
    else:
        ret += alpha
    return ret


N = int(input())
matrix = [list(map(int, input().split())) for _ in range(N)]
visit = [[False for _ in range(N)] for _ in range(N)]
answer = 0
# 1. 회전 이동 확인
s = [N//2, N//2]
direction = [(0, -1), (1, 0), (0, 1), (-1, 0)] # l d r u
ind = 0
visit[s[0]][s[1]] = True
while s != [0, 0]:
    s[0] += direction[ind][0]
    s[1] += direction[ind][1]
    visit[s[0]][s[1]] = True
    # 2. 모래 이동
    answer += sand_move(s, ind, matrix)
    # 1.1 회전
    ind = (ind + 1) % 4
    if visit[s[0] + direction[ind][0]][s[1] + direction[ind][1]]:
        ind = (ind - 1) % 4
print(answer)

시뮬레이션 문제여서 꽤 오래 걸린 문제였다.

이 문제는 두 단계로 나눠서 풀었는데 첫번째는 토네이도 이동하는 것을 먼저 구현했고 두번째는 모래가 흩날리는 것을 구현했다. 이때 두번째 부분에서 하드코딩으로 풀었다.

첫번째 토네이도 이동은 가장 안쪽에서부터 반시계방향으로 도는 것을 구현해야했는데 direction으로 움직여야할 방향을 적어두고 위치를 갱신 했다. 갱신한 이후에는 무조건 회전을 하게 했는데 다음 단계에 회전할 위치를 방문 한 경우 다시 되돌렸다. 이렇게 했을때 N=5의 격자에서 원하는 순서대로 나오는 것을 확인하였다. 

두번째는 모래가 흩날리는 것이었는데 토네이도가 회전하기 전에 모래이동을 하게끔 구현하였다. 모래 이동은 함수로 따로 구현을 했다. 이 때 위에서 부터 확률과 해당 확률이 들어갈 상대적 위치를 적었고 값을 계산하여 갱신하였다. 그리고 격자 바깥으로 나가는 모래의 양을 리턴해서 모든 위치에서 함수를 돌았을때 전체 양을 출력하게 하였다.

 

많이 어려운 문제는 아니었지만 회전했을때를 생각하는게 조금 오래걸렸다.