본문 바로가기
Computer Science/Algorithm

[백준] 20057 - 마법사 상어와 토네이도(Python)

by 수제햄버거 2020. 12. 7.
728x90
반응형

문제출처 :

www.acmicpc.net/problem/20057

 

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

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

www.acmicpc.net

문제 풀이:

  • 2020년 삼성 하반기 오후의 1번문제로 나왔던 문제이다. 
  • 나는 1,2번중 1번만 1시간 30분만에 풀었고 코테 합이였다.
  • 이 문제의 경우 그냥 여태까지 삼성 기출의 구현처럼 풀면 크게 어려움 없이 풀린다.
  • 여러가지로 스마트 하게 짤 수 도 있지만 사실 그정도로 짤 필요가 있나 하는 생각에 생으로 코딩했다. 
    규칙성 만 찾으면 어렵지 않았던 것 같다.
  • 나는  2가지로 나눠서 풀었는데
    1) point가 움직이는 방법
    2) 움직임에 따라 모래가 밀리는 방법
    으로 풀었다.
  1. point가 움직이는 방법
    - NxN 일 때 0~N-2까지 순회를 돈다. 이때 idx(순회도는)가 짝수면 idx 만큼 왼쪽, 아래로 간다
    홀수면 idx만큼 오른쪽 , 위로 간다.
    ex) idx =2 
    -> ←←↓↓
    idx =3
    -> →→

    이후에 idx=N-1일땐 무조건 N-1번만큼
    ←으로 이동한다.
  2. 각각의 이동시 모래가 들어갈 양을 미리 좌표더하기 및 비율로 만들어서 구했다.
    조금 헤맷던 부분은 남은 모래를 계산할때였다. 
    처음에는 남은 모래를 계산하기 위해서 매번 모래가 이동할때 처음 모래에서 이동하는 모래의 양을 빼주었는데 그런경우 다음에 이동할 모래의 양이 달라지기 때문에 따로 관리해주어야한다. 즉 처음의 모래양에서 비율에 맞는 모래양을 다 구한다음에 이동시켜주고 빼주어야 한다.
#import numpy as np

n = int(input())
maps = [list(map(int,input().split())) for _ in range(n)]
out_sand =0

def Push_Sand(d,sand,x,y):
    global maps,out_sand,n
    #print(sand,x,y)
    first_sand = sand
    move_left =[(-1,0,0.07),(-2,0,0.02),(1,0,0.07),(2,0,0.02),(-1,1,0.01),(1,1,0.01),
              (-1,-1,0.1),(1,-1,0.1),(0,-2,0.05)]
    move_right=[(-1,0,0.07),(-2,0,0.02),(1,0,0.07),(2,0,0.02),(-1,-1,0.01),(1,-1,0.01),
              (-1,1,0.1),(1,1,0.1),(0,2,0.05)]
    move_up = [(-1,-1,0.1),(-1,1,0.1),(0,1,0.07),(0,-1,0.07),(1,-1,0.01),(1,1,0.01),
               (-2,0,0.05),(0,-2,0.02),(0,2,0.02)]
    move_down = [(-1,-1,0.01),(-1,1,0.01),(0,-1,0.07),(0,1,0.07),(0,-2,0.02),(0,2,0.02),
                 (1,-1,0.1),(1,1,0.1),(2,0,0.05)]
    move_list = [move_up,move_down,move_right,move_left]
    last_move = [(-1,0,1),(1,0,1),(0,1,1),(0,-1,1)]
    for i in move_list[d]:
        temp_x = x+ i[0]
        temp_y = y+ i[1]
        temp_sand = int(first_sand*i[2])
        sand -= temp_sand
        #print(temp_sand,sand,i[2])
        if(temp_x<0 or temp_x >=n or temp_y<0 or temp_y >=n):
            out_sand+= temp_sand
            continue
        maps[temp_x][temp_y] += temp_sand

    last_x = x+last_move[d][0]
    last_y = y+last_move[d][1]
    if(last_x>=n or last_x<0 or last_y >=n or last_y<0):
        out_sand+= sand
    else:
        maps[last_x][last_y] += sand

    #show_maps()


def show_maps():
    global maps
    #print(np.array(maps))
    #print()

#init
finger = [n//2,n//2]
#up,down,right,left
direction = [(-1,0),(1,0),(0,1),(0,-1)]

#move_finger
for idx in range(n-1):
    if(idx%2==0):
        #left,down
        for _ in range(idx+1):
            finger[0] = finger[0]+direction[3][0]
            finger[1] = finger[1]+direction[3][1]

            temp = maps[finger[0]][finger[1]]
            maps[finger[0]][finger[1]]=0
            Push_Sand(3,temp,finger[0],finger[1])

        for _ in range(idx+1):
            finger[0] = finger[0]+direction[1][0]
            finger[1] = finger[1]+direction[1][1]

            temp = maps[finger[0]][finger[1]]
            maps[finger[0]][finger[1]]=0
            Push_Sand(1,temp,finger[0],finger[1])

    else:
        #right,up
        for _ in range(idx + 1):
            finger[0] = finger[0]+direction[2][0]
            finger[1] = finger[1]+direction[2][1]

            temp = maps[finger[0]][finger[1]]
            maps[finger[0]][finger[1]] = 0
            Push_Sand(2, temp, finger[0], finger[1])


        for _ in range(idx + 1):
            finger[0] = finger[0]+direction[0][0]
            finger[1] = finger[1]+direction[0][1]
            temp = maps[finger[0]][finger[1]]
            maps[finger[0]][finger[1]] = 0
            Push_Sand(0, temp, finger[0], finger[1])


for _ in range(n):
    finger[0] = finger[0] + direction[3][0]
    finger[1] = finger[1] + direction[3][1]
    temp = maps[finger[0]][finger[1]]
    maps[finger[0]][finger[1]]=0
    Push_Sand(3,temp,finger[0],finger[1])

print(out_sand)
반응형