알고리즘/백준
[백준] 7562 : 나이트의 이동 - 자바(JAVA)
Junuuu
2022. 3. 9. 00:01
반응형
https://www.acmicpc.net/problem/7562
7562번: 나이트의 이동
체스판 위에 한 나이트가 놓여져 있다. 나이트가 한 번에 이동할 수 있는 칸은 아래 그림에 나와있다. 나이트가 이동하려고 하는 칸이 주어진다. 나이트는 몇 번 움직이면 이 칸으로 이동할 수
www.acmicpc.net
문제해석
나이트는 다음그림과 같이 이동할 수 있습니다.
나이트가 이동하려는 칸이 주어질때 나이트는 몇 번 움직여서 목적지로 이동할 수 있을까요?
입력
입력의 첫째 줄에는 테스트 케이스의 개수가 주어집니다.
각 테스트 케이스는 3줄로 이루어져 있습니다.
1. 체스판의 한 변의 길이 l 이 주어집니다. (체스판의 크기는 l x l 입니다)
2. 나이트가 현재 있는 칸이 주어집니다.
3. 나이트가 이동하려고 하는 칸이 주어집니다.
제약조건
4<= l <= 300
출력
각 테스트 케이스 마다 나이트가 최소 몇번만에 이동할 수 있는지 출력합니다.
문제 풀이 전 설계
나이트가 좌표계를 움직이며 최단 거리로 이동하는 방법을 찾아야 합니다.
DFS 와 BFS가 떠오르지만 최단 거리로 이동해야 하므로 BFS를 사용하면 될 것 같습니다.
보통 좌표의 탐색을 상하좌우로 하지만 여기서 특이한점은 나이트의 특별한 이동이 있기 때문에 이를 고려하면 됩니다.
만약 나이트가 방문한곳을 또 방문하는경우는? 절대 최단거리가 될 수 없습니다.
코드
package day0208;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
class Knight {
int currentY;
int currentX;
int moveCount;
Knight(int currnetY, int currentX, int moveCount) {
this.currentY = currnetY;
this.currentX = currentX;
this.moveCount = moveCount;
}
}
class Destination {
int destinationX;
int destinationY;
Destination(int destinationY, int destinationX) {
this.destinationY = destinationY;
this.destinationX = destinationX;
}
}
public class Main_7562_나이트의이동 {
// 좌상2개 , 우상 2개, 우하 2개, 우좌 2개
static int[] dy = { -1, -2, -2, -1, 2, 1, 2, 1 };
static int[] dx = { -2, -1, 1, 2, 1, 2, -1, -2 };
static final int SEARCH_COUNT = 8;
static int size;
static int[][] chessBoard;
static boolean[][] visited;
static Queue<Knight> queue = new LinkedList<Knight>();
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int testCase = Integer.parseInt(br.readLine());
StringBuilder sb = new StringBuilder();
for (int t = 0; t < testCase; t++) {
// 보드 초기화
size = Integer.parseInt(br.readLine());
chessBoard = new int[size][size];
visited = new boolean[size][size];
// 나이트 위치
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
Knight knight = new Knight(Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken()), 0);
// 목적지
st = new StringTokenizer(br.readLine(), " ");
Destination destination = new Destination(Integer.parseInt(st.nextToken()),
Integer.parseInt(st.nextToken()));
// 메인로직 BFS
queue.add(knight);
visited[knight.currentY][knight.currentX] = true;
while (!queue.isEmpty()) {
Knight tempKnight = queue.poll();
if (isArrived(tempKnight, destination)) {
sb.append(tempKnight.moveCount + "\n");
break;
}
tempKnight.moveCount++;
for (int i = 0; i < SEARCH_COUNT; i++) {
int tempY = tempKnight.currentY + dy[i];
int tempX = tempKnight.currentX + dx[i];
if (!isValid(tempY, tempX)) {
continue;
}
queue.add(new Knight(tempY, tempX, tempKnight.moveCount));
visited[tempY][tempX] = true;
}
}
queue.clear();
}
System.out.print(sb.toString());
}
// 나이트의 목적지 도착 검사
static boolean isArrived(Knight k, Destination d) {
return (k.currentX == d.destinationX && k.currentY == d.destinationY);
}
// 유효성 검사 : 배열 index + visited
static boolean isValid(int tempY, int tempX) {
return (tempY >= 0 && tempX >= 0 && tempY <= size-1 && tempX <= size-1 && visited[tempY][tempX] != true);
}
}