티스토리 뷰
문제 요약
- 알고리즘 분류: bfs, 구현, 시물레이션
- 난이도:Silver1
- 문제내용:
- 테스트 케이스 개수가 주어진다
- 각 테스트 케이스마다 한변의 정사각형 길이, 시작점, 도착점을 준다.
- 나이트가 시작점에 도착점까지 최소 이동을 구해라
7562번: 나이트의 이동
체스판 위에 한 나이트가 놓여져 있다. 나이트가 한 번에 이동할 수 있는 칸은 아래 그림에 나와있다. 나이트가 이동하려고 하는 칸이 주어진다. 나이트는 몇 번 움직이면 이 칸으로 이동할 수
www.acmicpc.net
문제풀이
이번 문제는 BFS 탐색 문제이다. BFS 탐색 알고리즘에 관한 자세한 설명은 여기에서 확인 해보면 알 수 있다.
기존 BFS는 각 노드간의 탐색인데 이번에는 2차원 배열로 응용한 BFS 탐색이다. 노드 대신 2차원 배열로 변경 된것만 생각하면 된다.
문제 접근 방법
이번 문제의 주는 BFS + 시물레이션 2개를 구현 해야 한다. 일단 시물레이션은 어떻게 구현 해야 하는지 부터 봐야 한다.
우선 나이트가 이동 할수 있는 위치를 알아야 한다. 나이트 이동하는 방향은 앞/뒤/좌/ 우으로 2칸 + 이동하는 대각선 1칸이고 이동할수 있는 범위는 총 8가지가 나오고 좌표는 위 그림으로 표현 할수 있다. 그러면 좌표는 아래와 같이 표현이 가능하다.
{{-2, -1}, {-2, 1}, {-1, -2}, {-1, 2}, {1, -2}, {1, 2}, {2, -1}, {2 , 1}}
위 8가지 방향으로 범위 안에 이동을 하면된다.
시뮬레이션 부분은 끝났으니 그 다음은 BFS 탐색을 구현만 하면된다. 기존 BFS는 방문 여부를 체크해서 처리를 했다면 이번 문제에서는 2차원 배열을 방문여부를 체크해서 나가면 된다. 근데 2차원 방문 여부 배열을 만들려고 하니까 또 새로 만들어야 하는것은 아니다. 최소 방문 개수라서 모든 2차원 배열은 0으로 시작해서 방문 했을때 0일 때만 아래 그림처럼 이전 방문에 +1씩 해주기만 하면된다. 탐색이 끝났으면 도착점 개수를 출력만 해주면 끝이다.
정리
- 나이트 8개 좌표를 선언한다.
- 2차원 배열을 선언후 모두 0으로 초기화 한다.
- 시작점 부터 8개 좌표로 이동하면서 BFS 탐색을 한다.
- 2차원 배열 범위 안이고 0일때 이전 방문한 좌표값에서 + 1을해준다.
Code
Python
import sys
from collections import deque
input = sys.stdin.readline
# 나이트 이동할수 있는 좌표
dx = [-2, -2, -1, -1, 1, 1, 2, 2]
dy = [-1, 1, -2, 2, -2, 2, -1, 1]
def dfs(n):
fields = [[0] * n for i in range(n)]
queue = deque([start])
while queue:
x, y = queue.popleft()
if end == [x, y]:
break
for i in range(8):
fx, fy = x + dx[i], y + dy[i]
if 0<= fx < n and 0 <= fy < n and fields[fx][fy] == 0:
fields[fx][fy] = fields[x][y] + 1
queue.append((fx, fy))
return fields[end[0]][end[1]]
for _ in range(int(input())):
size = int(input())
start = list(map(int, input().split()))
end = list(map(int, input().split()))
print(dfs(size))
Java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
public class Main {
// 나이트 이동할수있는 좌표
static int[] dx = {-2, -2, -1, -1, 1, 1, 2, 2};
static int[] dy = {-1, 1, -2, 2, -2, 2, -1, 1};
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
StringTokenizer st;
int[] start, end;
int size;
while(N-- > 0) {
size = Integer.parseInt(br.readLine());
st = new StringTokenizer(br.readLine());
start = new int[] {Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken())};
st = new StringTokenizer(br.readLine());
end = new int[] {Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken())};
System.out.println(bfs(size, start, end));
}
}
public static int bfs(int size, int[] start, int[] end) {
int[][] fields = new int[size][size];
Queue<int[]> queue = new LinkedList<int[]>();
queue.add(start);
int x, y, fx, fy;
int[] location;
while (!queue.isEmpty()) {
location = queue.poll();
x = location[0];
y = location[1];
if(x == end[0] && y == end[1]) break;
for(int i = 0; i < 8; i++) {
fx = x + dx[i];
fy = y + dy[i];
// 필드 범위 안이거나 방문 하지 않았을 경우
if(0 <= fx && fx < size && 0<= fy && fy < size && fields[fx][fy] == 0) {
fields[fx][fy] = fields[x][y] + 1;
queue.add(new int[] {fx, fy});
}
}
}
return fields[end[0]][end[1]];
}
}
'알고리즘 > 백준' 카테고리의 다른 글
[BAEKJOON]1946 신입 사원 (0) | 2023.02.10 |
---|---|
[BAEKJOON]11052 카드 구매하기 (0) | 2023.02.09 |
[BAEKJOON]1850 최대공약수 (0) | 2023.02.07 |
[BAEKJOON]11057 오르막 수 (0) | 2023.02.04 |
[BAEKJOON]24445 알고리즘 수업 - 너비 우선 탐색 2 (0) | 2023.02.03 |
- Total
- Today
- Yesterday
- 조합
- 동적계획법
- 누적합
- Programmerse
- BFS
- java
- 이론
- 알고리즘
- spring-boot
- DFS
- Python
- 구현
- DP
- Greedy
- 자바
- 문자열
- JSCODE
- 재귀호출
- 백준
- level2
- LeetCode
- 파이썬
- 그래프
- BaekJoon
- 배열
- 그리디
- 백트레킹
- 수학
- 넓이 우선 탐색
- 동적 계획법
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |