ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준] 7562번: 나이트의 이동
    Coding/Problem Solving & Algorithm 2022. 12. 18. 15:31

    문제 링크 : https://www.acmicpc.net/problem/7562

    문제

    체스판 위에 한 나이트가 놓여져 있다. 나이트가 한 번에 이동할 수 있는 칸은 아래 그림에 나와있다. 나이트가 이동하려고 하는 칸이 주어진다. 나이트는 몇 번 움직이면 이 칸으로 이동할 수 있을까?

    입력

    입력의 첫째 줄에는 테스트 케이스의 개수가 주어진다.

    각 테스트 케이스는 세 줄로 이루어져 있다. 첫째 줄에는 체스판의 한 변의 길이 l(4 ≤ l ≤ 300)이 주어진다. 체스판의 크기는 l × l이다. 체스판의 각 칸은 두 수의 쌍 {0, ..., l-1} × {0, ..., l-1}로 나타낼 수 있다. 둘째 줄과 셋째 줄에는 나이트가 현재 있는 칸, 나이트가 이동하려고 하는 칸이 주어진다.

    출력

    각 테스트 케이스마다 나이트가 최소 몇 번만에 이동할 수 있는지 출력한다.


    우선 입력을 구현하자.

    세 줄에 걸쳐 체스판 한 변의 길이,  현재 나이트의 좌표, 나이트의 목적지가 주어진다.

     

    testCase = int(input())
    
    for _ in range(testCase):
        l = int(input())
        curCoor = tuple(map(int, input().split()))
        dstCoor = tuple(map(int, input().split()))

     

    너비 우선 탐색 (BFS)를 이용해서 구현할 수 있어보인다.

    체스판을 좌표로 하고 나이트가 이동할 수 있는 칸을 리스트로 저장해준다.

    knightMv = [(1,2),(2,1),(-1,2),(-2,1),(1,-2),(2,-1),(-1,-2),(-2,-1)]

     

    그 다음 현재 좌표에서 knigthMv 리스트의 원소를 하나씩 반복해 더해주면서 이동할 수 있는 칸을 찾는다.

    이후 도착한 좌표에 현재 좌표까지 도달하는데 걸리는 이동 횟수를 더해준다.

    마지막으로 목표 지점에 도달하면 loop를 break하고 해당 좌표까지 걸린 도달 횟수를 출력해주면 된다.

     

    from collections import deque
    
    def BFS(l, start:tuple, end:tuple):
        
        knightMv = [(1,2),(2,1),(-1,2),(-2,1),(1,-2),(2,-1),(-1,-2),(-2,-1)]
    
        visited = [[0 for i in range(l)] for j in range(l)] # 체스판 모든 칸을 0으로 초기화
        q = deque()
        q.appendleft(start)
    
        while q:
    
            curCoor = q.pop()
            for mv in knightMv:	# 현재 좌표에서 나이트가 움직일 수 있는 위치를 각각 더해준다
                
                if (curCoor[0]+mv[0]<0 or curCoor[0]+mv[0]>=l): # x 좌표 범위 확인
                    continue
                if (curCoor[1]+mv[1]<0 or curCoor[1]+mv[1]>=l): # y 좌표 범위 확인
                    continue
                if visited[curCoor[0]+mv[0]][curCoor[1]+mv[1]]: # 방문 여부 확인
                    continue
                
                q.appendleft((curCoor[0]+mv[0],curCoor[1]+mv[1]))
                visited[curCoor[0]+mv[0]][curCoor[1]+mv[1]] = visited[curCoor[0]][curCoor[1]] + 1
    
            if visited[end[0]][end[1]]:
                break
    
        return visited[end[0]][end[1]]

     

    이 상태에서 테스트 케이스를 돌려봤더니 시작 지점과 도착  지점이 같은 경우 이동 횟수가 2로 출력된다.

    마지막 예외처리를 해주었다. 

        if start == end:
            return 0

     

    최종 코드는 아래와 같다. 

    from collections import deque
    
    def BFS(l, start:tuple, end:tuple):
    
        if start == end:
            return 0
                
        knightMv = [(1,2),(2,1),(-1,2),(-2,1),(1,-2),(2,-1),(-1,-2),(-2,-1)]
    
        visited = [[0 for i in range(l)] for j in range(l)]
        q = deque()
        q.appendleft(start)
    
        while q:
    
            curCoor = q.pop()
            for mv in knightMv:
                
                if (curCoor[0]+mv[0]<0 or curCoor[0]+mv[0]>=l): 
                    continue
                if (curCoor[1]+mv[1]<0 or curCoor[1]+mv[1]>=l):
                    continue
                if visited[curCoor[0]+mv[0]][curCoor[1]+mv[1]]:
                    continue
                
                q.appendleft((curCoor[0]+mv[0],curCoor[1]+mv[1]))
                visited[curCoor[0]+mv[0]][curCoor[1]+mv[1]] = visited[curCoor[0]][curCoor[1]] + 1
    
            if visited[end[0]][end[1]]:
                break
    
        return visited[end[0]][end[1]]
    
    
    testCase = int(input())
    
    for _ in range(testCase):
    
        l = int(input())
        strCoor = tuple(map(int, input().split()))
        dstCoor = tuple(map(int, input().split()))
        
        print(BFS(l, strCoor, dstCoor))

     

    역시 파이썬이 좋다.

    'Coding > Problem Solving & Algorithm' 카테고리의 다른 글

    [백준] 7571번: 크래머의 공식  (0) 2022.12.19

    댓글

Designed by Tistory.