Posts [baekjoon] 20057. 마법사 상어와 토네이도 (python)
Post
Cancel

[baekjoon] 20057. 마법사 상어와 토네이도 (python)

20057. 마법사 상어와 토네이도 문제 바로가기

해결 방법

  1. 가장 먼저 토네이도 방향을 순서대로 돌기 위한 코드를 작성했습니다.

    마법사 상어와 토네이도 문제 그림

    1 → 1 → 2 → 2→ 3 → 3 → 4 → …

    몇 칸을 이동하고 방향이 바뀌는 지의 규칙을 살펴보면 1부터 시작하여 칸의 이동이 2번 같으면 + 1를 하여 이동한다!

    따라서 move_cnt라는 리스트를 이용하여 [이동할 칸 수, 해당 칸의 이동이 몇번째인지] 를 저장하여 이동할 칸 수(move_cnt[0])는 처음에 1로 설정하고 move_cnt[1] 가 2가 되면 move_cnt[0]를 + 1 하도록 작성하였습니다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    
    N = int(input())
    board = [list(map(int, input().split())) for _ in range(N)]
    y, x, d = N // 2, N // 2, 0
       
    dirs = [[0, -1], [1, 0], [0, 1], [-1, 0]]
       
    move_cnt = [1, 0] # 움직이는 방향 바꾸는 기준이 될 리스트
    check = [[0] * N for _ in range(N)]
    frag = False
    c = 1 
    while True:
        if frag: break # 종료조건
        check[y][x] = c
        for _ in range(move_cnt[0]):
            y += dirs[d][0]
            x += dirs[d][1]
            if [y, x] == [0, 0]:
                frag = True
            c += 1
            check[y][x] = c # 이동하는 방향을 확인하기 위해 c 변수를 통해 check 리스트에 이동 경로를 체크한다.
    		# 여기!!! 위치 확정된 부분이기에 이부분에 모래를 흩날리면 된다!!
       
        d += 1
        if d == 4: d = 0
        move_cnt[1] += 1
        if move_cnt[1] == 2: # 움직이는 방향 바꾸기
            move_cnt[0] += 1
            move_cnt[1] = 0
       
    for c in range(N):
        print(check[c])
           
    """ 
    출력값 : 원하는 순서대로 이동하는 것 확인 
    [25, 24, 23, 22, 26]
    [10, 9, 8, 7, 20]
    [11, 2, 1, 6, 19]
    [12, 3, 4, 5, 18]
    [13, 14, 15, 16, 17]
    """
    

    출력값을 통해 원하는 움직임으로 동작하는 것을 확인할 수 있습니다. 따라서 이제 이동할 때마다 모래의 흩날리는 동작을 구현하면 됩니다.

  2. 이동할 때 마다 해당 위치별 모래가 흩날리도록 동작하는 코드를 작성하였습니다.

    마법사 상어와 토네이도 문제 그림2

    다음 그림과 같이 tornado_dirs에 x에서 y로의 4가지 방향별로 y의 위치를 기준으로 어느 위치에서 해당 비율을 뿌려야하는 지 저장하였습니다.

    일정한 비율로 흩날리기에 tornado = [0.02, 0.01, 0.07, 0.1] 리스트를 이용하여 해당 부분을 계산하고 5% 부분(노란색), 알파 부분(회색) 순으로 뿌려질 모래를 계산하도록 하였습니다.

    이때 격자 밖으로 튀어나갈 경우에 answer 값에 모래를 더했습니다.

구현한 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
N = int(input())
board = [list(map(int, input().split())) for _ in range(N)]
y, x, d = N // 2, N // 2, 0 # 시작좌표와 방향 설정

dirs = [[0, -1], [1, 0], [0, 1], [-1, 0]]
tornado_dirs = [ # 토네이도로 흩날릴 방향 저장
    [[-2, 0], [2, 0], [-1, 1], [1, 1], [-1, 0], [1, 0], [-1, -1], [1, -1], [0, -2], [0, -1]],
    [[0, -2], [0, 2], [-1, -1], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 1], [2, 0], [1, 0]], 
    [[2, 0], [-2, 0], [1, -1], [-1, -1], [1, 0], [-1, 0], [1, 1], [-1, 1], [0, 2], [0, 1]],
    [[0, 2], [0, -2], [1, 1], [1, -1], [0, 1], [0, -1], [-1, 1], [-1, -1], [-2, 0], [-1, 0]]
]
move_cnt = [1, 0] # 움직이는 방향 바꾸는 기준이 될 리스트

frag = False # 종료 조건의 기준
answer = 0 # 격자 밖으로 나간 모래의 양 저장할 변수
while True:
    if frag: break # 종료조건
    for _ in range(move_cnt[0]): # 한방향으로 이동하는 횟수
        y += dirs[d][0]
        x += dirs[d][1]
        if [y, x] == [0, 0]: # 최종 이동이기에 frag = True로 바꾸기
            frag = True

        # 모래 흩날리는 과정
        sand = board[y][x] # y 칸의 모래양 저장
        board[y][x] = 0
        temp_sand = 0 # 남은 모래 알파의 값을 저장할 변수
        for t in range(4):
            tornado = [0.02, 0.01, 0.07, 0.1]
            for t2 in range(2):
                temp_sand += int(sand * tornado[t]) # 모래에 비율을 곱하여 위치에 뿌려질 모래의 양 구하기
                ty, tx = y + tornado_dirs[d][2 * t + t2][0], x + tornado_dirs[d][2 * t + t2][1] # 모래를 뿌릴 위치 구하기
                if 0 <= ty < N and 0 <= tx < N: 
                    board[ty][tx] += int(sand * tornado[t]) 
                else: # 격자 밖으로 나간 모래의 양
                    answer += int(sand * tornado[t])
        ty, tx = y + tornado_dirs[d][8][0], x + tornado_dirs[d][8][1]
        temp_sand += int(sand * 0.05) # 5% 부분 계산
        if 0 <= ty < N and 0 <= tx < N:
            board[ty][tx] += int(sand * 0.05)
        else:  # 격자 밖으로 나간 모래의 양
            answer += int(sand * 0.05)
				# 알파 부분 계산
        ly, lx = y + tornado_dirs[d][9][0], x + tornado_dirs[d][9][1]
        if 0 <= ly < N and 0 <= lx < N:
            board[ly][lx] += sand - temp_sand
        else:  # 격자 밖으로 나간 모래의 양
            answer += sand - temp_sand

    # 토네이도의 이동, 방향 결정
    d += 1
    if d == 4: d = 0
    move_cnt[1] += 1
    if move_cnt[1] == 2: # 움직이는 방향 바꾸기
        move_cnt[0] += 1
        move_cnt[1] = 0

print(answer)
This post is licensed under CC BY 4.0 by the author.

[baekjoon] 20056. 마법사 상어와 파이어볼 (python)

[baekjoon] 17837. 새로운 게임2 (python)

Comments powered by Disqus.