developer-ellen
인간 디버거의 로그 찍기
developer-ellen
전체 방문자
오늘
어제
  • 분류 전체보기 (217)
    • 회고록 (0)
    • 취뽀 및 커리어 여정의 Stack (2)
      • SSAFY 7기 (2)
    • 프로그래밍공부 (24)
      • c++ (0)
      • JAVA (3)
      • Spring (5)
      • design pattern (3)
      • BackDB (1)
      • Servlet&JSP (3)
      • Vue (4)
      • JPA (4)
      • Infra (1)
      • Linux (0)
    • AI (3)
      • papers (3)
      • trend (0)
    • 프로젝트진행 (0)
      • 데이터베이스 (0)
      • 서버개발 (0)
      • 인공지능 (0)
      • 하루정리 (0)
    • 포트폴리오 (0)
    • 알고리즘 (158)
      • 알고리즘문풀 (155)
      • 알고리즘공부 (3)
    • 통계공부 (15)
      • 시계열분석 (15)
      • 회귀분석 (0)
    • CS (14)
      • 컴퓨터네트워크 (4)
      • 운영체제 (8)
      • 데이터베이스 (2)
    • 주저리주저리 (0)
      • 필사 (0)
    • 취업관련정보 (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 삼성코테구현문제추천
  • 데이터분석
  • ARIMA모형
  • 통계분석
  • 삼성코테파이썬풀이
  • 삼성코테준비
  • Arima
  • 카카오코테
  • 삼성코테기출자바풀이
  • 삼성코테구현풀이
  • c++디자인패턴
  • 백준파이썬풀이
  • 삼성코테자바꿀팁
  • c++ 빌더 패턴
  • 코테파이썬
  • SW역량테스트파이썬
  • SW역량테스트파이썬풀이
  • 삼성코테자바풀이
  • 삼성코테파이썬준비
  • 삼성코테기출
  • MA모형
  • 삼성코테파이썬
  • 시계열
  • AR모형
  • 통계학
  • 운영체제인터럽트
  • 시계열분석
  • 삼성코테자바준비
  • BOJ파이썬풀이
  • 카카오코테java풀이

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
developer-ellen

인간 디버거의 로그 찍기

알고리즘/알고리즘문풀

BOJ - 마법사 상어와 토네이도 20057번 (python)

2021. 10. 21. 10:57

❓ 문제 - 백준 마법사 상어와 토네이도 20057번 - python 풀이법

 

출처 

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

 

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

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

www.acmicpc.net

 

 

📝 문제해결법

1. 이 문제는 구현으로 풀었다.

  • 격자판의 중심에서 토네이도가 이동했을 때 위치와 방향을 저장하기 위해 1 ~ n*n의 딕셔너리인 b_dict 선언하여 쉽게 접근할 수 있도록 구현하였다. 만약 토네이도가 한바퀴 다 이동하는 것은 딕셔너리의 1 ~ n*n까지의 키로 접근하면 몇 번째 이동의 위치와 방향을 얻을 수 있다.
  • b_dict에서 1번은 (격자판 중심이고) ~ 이동을 통해 n*n번은 (격자판의 0,0)를 가리키게 되며, b_dict 키에 맞는 value값은 해당 위치 행,열 값과 다음 이동 방향이다.
  • 토네이도가 이동하는 방향은 왼쪽-아래쪽-오른쪽-위쪽 순으로 규칙적으로 움직이며 방향을 바꾸기 까지 이동거리는 1,1,2,2,3,3,4,4,5,5 .... 순으로 아래쪽방향으로 움직이다가 오른쪽 방향으로 바뀔 때 방향을 유지한 채 이동하는 거리가 커지고, 위쪽방향에서 왼쪽방향으로 방향을 바뀔 때 방향을 유지한 채 이동하는 거리가 커진다. 토네이도에 방향을 유지한채 이동하는 거리는 [1, 1, 2, 2, 3, 3, ..., n-1, n-1, n]이다. 이동 거리를 go 리스트에 넣어 b_dict의 값들을 생성할 때 go[g_idx]만큼 이동했으면 방향을 바꾸고 g_idx 값을 1증가 시키고, go[g_idx] 만큼 이동하지 않았으면 해당 방향으로 계속 이동한 nx,ny값과 방향을 b_dict에 넣어준다.
  • 1 ~ n*n번의 키값으로 토네이도의 이동을 구현하는데 현재 위치와 움직이려는 방향, 그리고 다음 위치를 딕셔너리에서 가져온 후, 움직이려는 방향과 다음 위치, 그리고 moving() 함수로 모래를 흩날린다.
  • 모래를 흩날린 후 격자밖으로 나간 모래의 양 sand를 출력한다.

2. moving()

  • 토네이도가 움직이는 방향에 따라 모래가 흩날리는 비율을 left, right, up, down를 이용한다. 토네이도가 이동하면 모래를 흩날리는 위치인 x,y을 기준으로 행은 x-2 ~ x+2, 열은 y-2 ~ y+2을 살펴서 비율에 맞춰 모래를 흩날리면 된다.
  • 모래를 흩날리는 양의 알파 부분은 나머지 부분을 비율에 맞춰서 흩날린 후, 남은 양을 옮겨주면 되는데, 우선 나머지 부분을 비율에 맞춰 흩날리기 위해 만약 알파 부분이 오면 해당 알파 부분의 인덱스 a_x, a_y을 저장한다.
  • 나머지 비율에 맞춰서 모래를 흩날리기 전 만약 흩날릴 부분이 격자 밖이면 sand에 값을 더해주고,  격자 안이면 해당 인덱스에 맞춰 흩날릴 모래양을 격자판에 더해준다.
  • 나머지 부분을 비율에 맞춰 더해주고 남은 양을 알파부분에 더해주기 위해, 우선 알파 부분의 인덱스가 격자 밖이면 sand에 더해주고 격자 안이면 나머지 부분을 비율에 맞춰 더해주고 남은 양을 알파 부분에 더해준다.

3. 문제 풀고 느낀점

  • 방향에 따라 모래를 흩날리는 비율이 다른 부분을 함수로 구현하려다가 포기하고 방향에 따른 비율부분을 따로 리스트에 직접 입력하였다. -> ~에 따라 다른 부분을 구현해야할 갯수가 적으면 직접하자...^^
  • 토네이도의 움직임을 딕셔너리로 구현하는 부분에 시간을 너무 할애하였다... 이런 토네이도 부분 구현하는 것을 기억해두어 다음에 유사 문제가 나올 때 이용하자

 

 

💻 소스코드

n = int(input())
dx = [0, 1, 0, -1]
dy = [-1, 0, 1, 0]

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

b_dict = {}

x, y = n // 2, n // 2
s = 1
count = 0
d = 0
go = []
for i in range(1, n):
    go.append(i)
    go.append(i)
go.append(n)
g_idx = 0
b_dict[1] = [x, y, 0]
sand = 0

left = [[0,0,2,0,0],[0,10,7,1,0],[5,-1,0,0,0],[0,10,7,1,0],[0,0,2,0,0]]
right = [[0,0,2,0,0],[0,1,7,10,0],[0,0,0,-1,5],[0,1,7,10,0],[0,0,2,0,0]]
up = [[0,0,5,0,0],[0,10,-1,10,0],[2,7,0,7,2],[0,1,0,1,0],[0,0,0,0,0]]
down = [[0,0,0,0,0],[0,1,0,1,0],[2,7,0,7,2],[0,10,-1,10,0],[0,0,5,0,0]]

def moving(x, y, a, plus):
    global sand
    a_x, a_y = -1, -1
    remain = 0
    for i in range(-2, 3):
        for j in range(-2, 3):
            if plus[i+2][j+2] == 0 or plus[i+2][j+2] == -1:
                if plus[i+2][j+2] == -1:
                    a_x, a_y = i+2, j+2
                continue
            temp = int(a*(plus[i+2][j+2]/100))
            remain += temp
            if x+i < 0 or x+i >=n or y+j < 0 or y+j >= n:
                sand += temp
            else:
                board[x+i][y+j] += temp
    if 0 <= x+a_x-2 < n and 0<= y+a_y-2 < n:
        board[x+a_x-2][y+a_y-2] += (a-remain)
    else:
        sand += (a-remain)

for i in range(1, n*n):
    nx = x + dx[d]
    ny = y + dy[d]
    count += 1
    x, y = nx, ny
    if count >= go[g_idx]:
        d = (d+1) % 4
        b_dict[i + 1] = [nx, ny, d]
        g_idx += 1
        count = 0
    else:
        b_dict[i+1] = [nx, ny, d]

for i in range(1, n*n):
    x, y, d = b_dict[i]
    nx, ny, nd = b_dict[i+1]
    if d == 0:
        moving(nx, ny, board[nx][ny],left)
    elif d == 1:
        moving(nx, ny, board[nx][ny], down)
    elif d == 2:
        moving(nx, ny, board[nx][ny], right)
    else:
        moving(nx, ny, board[nx][ny], up)
    board[nx][ny] = 0

print(sand)

 

'알고리즘 > 알고리즘문풀' 카테고리의 다른 글

BOJ - 상어 중학교 21609번 (python)  (0) 2021.10.21
BOJ - 마법사 상어와 파이어스톰 20058번 (python)  (0) 2021.10.21
BOJ - 마법사 상어와 파이어볼 20056번 (python)  (0) 2021.10.20
BOJ - 컨베이어 벨트 위의 로봇 20055번 (python)  (0) 2021.10.20
BOJ - 스타트택시 19238번 (python)  (0) 2021.10.20
    '알고리즘/알고리즘문풀' 카테고리의 다른 글
    • BOJ - 상어 중학교 21609번 (python)
    • BOJ - 마법사 상어와 파이어스톰 20058번 (python)
    • BOJ - 마법사 상어와 파이어볼 20056번 (python)
    • BOJ - 컨베이어 벨트 위의 로봇 20055번 (python)
    developer-ellen
    developer-ellen

    티스토리툴바