목차
- 개요
- 본문
- 1) 문제
- 2) 과정
- 3) 코드 전체
개요
이번에 알고리즘 스터디에서 JAVA를 이용해 백준 7562번 나이트의 이동을 풀었습니다. 이를 정리해보고자 합니다.
7562번: 나이트의 이동
체스판 위에 한 나이트가 놓여져 있다. 나이트가 한 번에 이동할 수 있는 칸은 아래 그림에 나와있다. 나이트가 이동하려고 하는 칸이 주어진다. 나이트는 몇 번 움직이면 이 칸으로 이동할 수
www.acmicpc.net
본문
1) 문제
2) 과정
이번 문제를 푸는 데는 1시간 정도 걸렸습니다.
말을 이동시키는 것도 큐를 이용해 bfs를 구현하는것도 어느 정도 적응이 되어 그렇게 어렵거나 오래걸린 문제는 아니었습니다.
2-1) main
public static void main(String[] args) throws IOException{
// Input
int testcase = Integer.parseInt(reader.readLine()); // 테스트 케이스의 수
for(int loop = 0 ; loop< testcase; loop++){
size = Integer.parseInt(reader.readLine()); // 체스의 한 변의 크기
String[] sLine = reader.readLine().split(" "); // 시작 위치
Node start = new Node(Integer.parseInt(sLine[0]),Integer.parseInt(sLine[1]));
String[] eLine = reader.readLine().split(" "); // 종료 위치
Node end = new Node(Integer.parseInt(eLine[0]),Integer.parseInt(eLine[1]));
// Initialize
int[][] dp = new int[size][size]; // 최소 이동횟수를 담는다.
boolean[][] visited = new boolean[size][size]; // 방문 여부를 담는다.
Queue<Node> kQueue = new LinkedList<>(); // 각 나이트들의 위치를 담는다.
visited[start.x][start.y] = true; // 시작 위치 방문 true로 셋팅(시작과 종료의 위치가 같을 때 다른 곳을 다녀오지 않도록 해야하기 때문에)
kQueue.add(start); // 시작 위치 큐에 담기
// Logic
while(!kQueue.isEmpty()){
// 큐에서 좌표 가져오기
Node node = kQueue.poll();
for(int i=0;i<8;i++){ // 나이트의 이동가능한 위치를 모두 탐색
// 임시 좌표 설정
int tmpX = node.x+xDiff[i];
int tmpY = node.y+yDiff[i];
Node tmp = new Node(tmpX, tmpY);
// 범위 체크(체스판을 벗어나는지 여부)
if(!checkBound(tmp)) continue;
// 방문 체크(이미 방문했던 위치인지 여부 - bfs이기 때문에 계속 커지는 count의 특성 상 더 작은 경우가 나올 수 없어 visited면 다시 방문하지 않도록 체크)
if(visited[tmpX][tmpY]) continue;
visited[tmpX][tmpY] = true;
// dp값(해당 좌표까지의 최소 이동횟수) 넣기.
dp[tmpX][tmpY] = dp[node.x][node.y]+1;
// 큐에 넣어 더이상 탐색할 수 없을 때까지 탐색 진행.
kQueue.add(tmp);
}
}
// Output
System.out.println(dp[end.x][end.y]);
}
}
// Method
private static boolean checkBound(Node node){return 0<=node.x && node.x<size && 0<=node.y && node.y<size;}
이번엔 문제를 푼 후 주석으로 설명을 첨부하였습니다.
주석을 보고 이해안되거나 어려웠던 부분이 있으시다면 댓글 남겨주시면 감사하겠습니다.
읽어오는 것 관련된 정보는 아래 링크를 확인해주세요 :)
[개념정리] System.in / InputStreamReader / BufferedReader 정리
개요 앞으로도 BufferedReader를 사용하며 자주 언급할 것 같아 한번에 정리해두고자 작성했다. 본론 BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 자주사용하는 BufferedRead..
codingjerk-diary.tistory.com
2-2) Inner Class
// Inner Class
private static class Node{
int x, y;
public Node(int x, int y){
this.x=x;
this.y=y;
}
}
}
Inner Class로 말의 좌표를 담는 Node 클래스는 위와 같습니다. 단순하게 x와 y를 함께 저장할 수 있도록 구성하였습니다.
3) 전체코드
그렇게 완성된 코드는 다음과 같습니다.
package sujeong.dfs_bfs;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
public class BOJ7562 {
// Attribute
private static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
// Constants
private static final int[] xDiff = {1,2,2,1,-1,-2,-2,-1};
private static final int[] yDiff = {2,1,-1,-2,-2,-1,1,2};
// Variable
private static int size; // 체스 한 변의 크기
// Main
public static void main(String[] args) throws IOException{
// Input
int testcase = Integer.parseInt(reader.readLine()); // 테스트 케이스의 수
for(int loop = 0 ; loop< testcase; loop++){
size = Integer.parseInt(reader.readLine()); // 체스의 한 변의 크기
String[] sLine = reader.readLine().split(" "); // 시작 위치
Node start = new Node(Integer.parseInt(sLine[0]),Integer.parseInt(sLine[1]));
String[] eLine = reader.readLine().split(" "); // 종료 위치
Node end = new Node(Integer.parseInt(eLine[0]),Integer.parseInt(eLine[1]));
// Initialize
int[][] dp = new int[size][size]; // 최소 이동횟수를 담는다.
boolean[][] visited = new boolean[size][size]; // 방문 여부를 담는다.
Queue<Node> kQueue = new LinkedList<>(); // 각 나이트들의 위치를 담는다.
visited[start.x][start.y] = true; // 시작 위치 방문 true로 셋팅(시작과 종료의 위치가 같을 때 다른 곳을 다녀오지 않도록 해야하기 때문에)
kQueue.add(start); // 시작 위치 큐에 담기
// Logic
while(!kQueue.isEmpty()){
// 큐에서 좌표 가져오기
Node node = kQueue.poll();
for(int i=0;i<8;i++){ // 나이트의 이동가능한 위치를 모두 탐색
// 임시 좌표 설정
int tmpX = node.x+xDiff[i];
int tmpY = node.y+yDiff[i];
Node tmp = new Node(tmpX, tmpY);
// 범위 체크(체스판을 벗어나는지 여부)
if(!checkBound(tmp)) continue;
// 방문 체크(이미 방문했던 위치인지 여부 - bfs이기 때문에 계속 커지는 count의 특성 상 더 작은 경우가 나올 수 없어 visited면 다시 방문하지 않도록 체크)
if(visited[tmpX][tmpY]) continue;
visited[tmpX][tmpY] = true;
// dp값(해당 좌표까지의 최소 이동횟수) 넣기.
dp[tmpX][tmpY] = dp[node.x][node.y]+1;
// 큐에 넣어 더이상 탐색할 수 없을 때까지 탐색 진행.
kQueue.add(tmp);
}
}
// Output
System.out.println(dp[end.x][end.y]);
}
}
// Method
private static boolean checkBound(Node node){return 0<=node.x && node.x<size && 0<=node.y && node.y<size;}
// Inner Class
private static class Node{
int x, y;
public Node(int x, int y){
this.x=x;
this.y=y;
}
}
}
소요시간, 아이디어, 에러로그 등 더 자세히 보고싶으시다면, 아래 깃헙 링크를 참고해주세요 :)
https://github.com/Park1122/Algorithm-Study/blob/master/sujeong/dfs_bfs/BOJ7562.java
GitHub - Park1122/Algorithm-Study: 명지대학교 학생들이 모여서 만든 알고리즘 공부 및 코딩테스트 준비
명지대학교 학생들이 모여서 만든 알고리즘 공부 및 코딩테스트 준비를 위한 스터디입니다. Contribute to Park1122/Algorithm-Study development by creating an account on GitHub.
github.com
'알고리즘(JAVA 사용) > DFS & BFS' 카테고리의 다른 글
[알고리즘풀이]백준 1697 : 숨바꼭질 JAVA (0) | 2021.10.13 |
---|---|
[알고리즘풀이]백준 18404 : 현명한 나이트 JAVA (0) | 2021.10.13 |
[알고리즘풀이]백준 2644 : 촌수계산 JAVA (0) | 2021.10.13 |