백준 알고리즘

백준 - 1600번 말이되고 싶은 원숭이 python 문제풀이 [Hellfer]

Hellfer 2023. 11. 14. 21:34
728x90

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

 

1600번: 말이 되고픈 원숭이

첫째 줄에 정수 K가 주어진다. 둘째 줄에 격자판의 가로길이 W, 세로길이 H가 주어진다. 그 다음 H줄에 걸쳐 W개의 숫자가 주어지는데, 0은 아무것도 없는 평지, 1은 장애물을 뜻한다. 장애물이 있

www.acmicpc.net

🔷 알고리즘 분류 - BFS(너비우선탐색), 난이도 - 골드 3

🔶문제 풀이 - BFS(너비우선탐색)을 이용한 풀이

from collections import deque

# 말처럼 움직일 때 이동하는 방향
dx1 = [-2, -1, 1, 2, 2, 1, -1, -2]
dy1 = [1, 2, 2, 1, -1, -2, -2, -1]

# 평범하게 움직일 때 이동하는 방향
dx2 = [-1, 0, 1, 0]
dy2 = [0, 1, 0, -1]

def bfs():
    queue = deque()
    queue.append((0, 0, 0)) # x, y, k
    visited[0][0][0] = True

    while queue:
        x, y, k = queue.popleft() # 큐에서 원소를 하나 꺼냄
        # 목표 위치에 도달했다면 이동 횟수를 반환
        if x == H-1 and y == W-1:
            return visited[x][y][k] - 1

        # 말처럼 움직일 수 있는 경우
        if k < K:
            for i in range(8):
                nx = x + dx1[i]
                ny = y + dy1[i]
                # 맵의 범위를 벗어나지 않고, 장애물이 없으며, 아직 방문하지 않았다면
                if 0 <= nx < H and 0 <= ny < W and not grid[nx][ny] and not visited[nx][ny][k+1]:
                    # 방문 표시를 하고 이동 횟수를 기록
                    visited[nx][ny][k+1] = visited[x][y][k] + 1
                    queue.append((nx, ny, k+1))

        # 평범하게 움직이는 경우
        for i in range(4):
            nx, ny = x + dx2[i], y + dy2[i]
            # 맵의 범위를 벗어나지 않고, 장애물이 없으며, 아직 방문하지 않았다면
            if 0 <= nx < H and 0 <= ny < W and not grid[nx][ny] and not visited[nx][ny][k]:
                # 방문 표시를 하고 이동 횟수를 기록
                visited[nx][ny][k] = visited[x][y][k] + 1
                queue.append((nx, ny, k))

    # 모든 경우를 다 확인했는데도 목표 위치에 도달하지 못했다면 -1을 반환
    return -1

K = int(input()) # 말처럼 움직일 수 있는 횟수
W, H = map(int, input().split()) # 맵의 가로 크기와 세로 크기
grid = [list(map(int, input().split())) for _ in range(H)] # 맵 정보
visited = [[[0]*(K+1) for _ in range(W)] for _ in range(H)] # 각 위치를 방문했는지 여부를 저장하는 리스트

print(bfs()) # bfs 함수를 호출하여 결과를 출력

🔶 초보자를 위한 생각주머니 키우기

🔸문제요약

이 문제는 체스판과 같은 2차원 그리드에서 시작점에서 도착점까지 이동하는데 필요한 최소 이동 횟수를

찾는 문제입니다. 이동은 상하좌우로 한 칸 움직이거나, 말처럼 대각선 방향으로 두 칸 이동한 후, 그 방향으로 90도 회전하여 한 칸 움직이는 두 가지 방법이 있습니다. 그리고 말처럼 움직일 수 있는 횟수가 제한되어 있습니다.

🔸해결전략

이 문제를 해결하기 위해서는 BFS(너비 우선 탐색) 알고리즘을 사용하는 것이 가장 효과적입니다.

BFS는 시작점에서 가장 가까운 노드부터 차례로 방문하는 방식으로, 이 문제에서는 말처럼 움직일 수 있는 횟수를 고려하여 최소 이동 횟수를 찾습니다.

🔸코드요약

코드는 크게 세 부분으로 이루어져 있습니다.

 

1. 초기 설정: 이동 방향, BFS 함수, 맵 크기, 맵 정보, 방문 여부를 저장하는 리스트 등을 설정합니다.

 

2. BFS 함수: BFS 알고리즘을 구현한 부분으로, 큐를 사용하여 말처럼 움직일 수 있는 횟수를 고려하면서 이동할 수 있는 모든 위치를 방문하고, 이동 횟수를 기록합니다.

 

3. 결과 출력: BFS 함수를 호출하여 최소 이동 횟수를 출력합니다. 즉, 이 코드는 BFS 알고리즘을 사용하여 말처럼 움직일 수 있는 횟수를 고려하면서 시작점에서 도착점까지의 최소 이동 횟수를 찾는 방법입니다.

 

🤗파이팅입니다~ 여러분!!🤗

728x90