[ BOJ / Python ] 21610번 마법사 상어와 비바라기

황승환·2022년 4월 4일
0

Python

목록 보기
259/498


이번 문제는 삼성 기출로 구현, 시뮬레이션으로 분류된 문제이다. 우선 구현 문제의 경우에는 함수로 각각의 과정을 정의하는 것이 가장 깔끔하다고 생각하기 때문에 모든 과정을 함수로 구현하였다. 우선 비구름의 위치를 나타낼 리스트 clouds를 False로 채워 2차원으로 선언한 후에 초기 비구름의 위치인 clouds[n-1][0], clouds[n-1][1], clouds[n-2][0], clouds[n-2][1]를 True로 갱신해야 한다. 그리고 다음과 같은 함수들로 과정을 처리하였다.

  • 비구름을 생성하는 make_clouds 함수
  • 비구름을 움직이는 move_clouds 함수
  • 비가 내리고, 물복사버그가 일어나는 pouring 함수
  • 전체 바구니에 있는 물의 양을 구하는 get_sum 함수

make_clouds 함수는 먹구름 리스트를 순회하며 먹구름 리스트가 False이고 grid[i][j]가 2 이상일 때, True로 갱신해준 후에 grid[i][j]를 2 감소시켰다. 만약 True일 경우에는 False로 갱신하여 먹구름이 사라지는 것을 구현하였다.

move_clouds 함수는 False로 채워진 임시 리스트 tmp에 먹구름의 다음 위치를 %연산을 통해 구하여 True로 갱신시킨 후에 deepcopy를 이용하여 clouds로 옮겼다.

pouring 함수는 전체를 순회하며 먹구름이 있는 칸을 1 증가시키고, 물복사버그는 4개의 대각선 방향을 확인하여 조건에 성립할 경우에만 현재 칸을 1 증가시키도록 하였다.

  • n, m을 입력받는다.
  • grid를 입력받는다.
  • commands를 입력받는다.
  • dy, dx를 주어진 방향 순서로 저장한다.
  • clouds 리스트를 n*n의 크기의 리스트로 선언하고 False로 채운다.
  • clouds[n-1][0], clouds[n-1][1], clouds[n-2][0], clouds[n-2][1]를 True로 갱신한다.
  • make_clouds 함수를 선언한다.
    -> n번 반복하는 i에 대한 for문을 돌린다.
    --> n번 반복하는 j에 대한 for문을 돌린다.
    ---> 만약 clouds[i][j]가 False이고, grid[i][j]가 2 이상일 경우,
    ----> clouds[i][j]를 True로 갱신한다.
    ----> grid[i][j]를 2 감소시킨다.
    ---> 만약 clouds[i][j]가 True일 경우,
    ----> clouds[i][j]를 False로 갱신한다.
  • move_clouds 함수를 d, s를 인자로 갖도록 선언한다.
    -> clouds를 global로 선언한다.
    -> 임시 변수 tmp를 n*n의 크기의 리스트로 선언하고 False로 채운다.
    -> n번 반복하는 i에 대한 for문을 돌린다.
    --> n번 반복하는 j에 대한 for문을 돌린다.
    ---> 만약 clouds[i][j]가 True일 경우,
    ----> tmp[(i+s*dy[d])%n][(j+s*dx[d])%n]를 True로 갱신한다.
    -> tmp를 clouds에 deepcopy한다.
  • pouring 함수를 선언한다.
    -> n번 반복하는 i에 대한 for문을 돌린다.
    --> n번 반복하는 j에 대한 for문을 돌린다.
    ---> 만약 clouds[i][j]가 True일 경우,
    ----> grid[i][j]를 1 증가시킨다.
    -> n번 반복하는 i에 대한 for문을 돌린다.
    --> n번 반복하는 j에 대한 for문을 돌린다.
    ---> 만약 clouds[i][j]가 True일 경우,
    ----> 2부터 8까지 2씩 증가하는 l에 대한 for문을 돌린다.
    -----> 만약 i+dy[l]이 0 이상, n 미만이고, j+dx[l]이 0 이상, n 미만이고, grid[i+dy[l]][j+dx[l]]가 0보다 클 경우,
    ------> grid[i][j]를 1 증가시킨다.
  • get_sum 함수를 선언한다.
    -> 결과를 저장할 변수 result를 0으로 선언한다.
    -> n번 반복하는 i에 대한 for문을 돌린다.
    --> result에 grid[i]의 총 합을 더한다.
    -> result를 반환한다.
  • m번 반복하는 i에 대한 for문을 돌린다.
    -> move_clouds(commands[i][0], commands[i][1])를 호출한다.
    -> pouring()을 호출한다.
    -> make_clouds()를 호출한다.
  • get_sum()의 반환값을 출력한다.

Code

import copy
n, m=map(int, input().split())
grid=[list(map(int, input().split())) for _ in range(n)]
commands=[list(map(int, input().split())) for _ in range(m)]
dy=[0, 0, -1, -1, -1, 0, 1, 1, 1]
dx=[0, -1, -1, 0, 1, 1, 1, 0, -1]
clouds=[[False for _ in range(n)] for _ in range(n)]
clouds[n-1][0], clouds[n-1][1], clouds[n-2][0], clouds[n-2][1]=True, True, True, True
def make_clouds():
    for i in range(n):
        for j in range(n):
            if not clouds[i][j] and grid[i][j]>=2:
                clouds[i][j]=True
                grid[i][j]-=2
            elif clouds[i][j]:
                clouds[i][j]=False
def move_clouds(d, s):
    global clouds
    tmp=[[False for _ in range(n)] for _ in range(n)]
    for i in range(n):
        for j in range(n):
            if clouds[i][j]:
                tmp[(i+s*dy[d])%n][(j+s*dx[d])%n]=True
    clouds=copy.deepcopy(tmp)
def pouring():
    for i in range(n):
        for j in range(n):
            if clouds[i][j]:
                grid[i][j]+=1
    for i in range(n):
        for j in range(n):
            if clouds[i][j]:
                for l in range(2, 9, 2):
                    if 0<=i+dy[l]<n and 0<=j+dx[l]<n and grid[i+dy[l]][j+dx[l]]>0:
                        grid[i][j]+=1
def get_sum():
    result=0
    for i in range(n):
        result+=sum(grid[i])
    return result
for i in range(m):
    move_clouds(commands[i][0], commands[i][1])
    pouring()
    make_clouds()
print(get_sum())

profile
꾸준함을 꿈꾸는 SW 전공 학부생의 개발 일기

0개의 댓글