본문 바로가기
알고리즘&자료구조/BFS

백준 7562

by do_ng 2024. 4. 30.

문제분석

 

체스판 길이(size)
8 -> 8 * 8 
나이트의 최초 시작 지점(startPoint)
나이트가 이동하려고 하는 칸(endPoint)

--> endPoint까지 최소 몇번만에 이동할수 있는지?

0. 시작지점을 큐에 넣음 

1. 나이트가 이동할 수 있는 모든 방향을 미리 지정해둠 
어떻게 지정할 것인가? 
총 8가지 방향 
ex) 0,0 기준으로 생각해보기 (x : 행, y : 열) 
1. 왼쪽상단
대각선(열감소, 행감소) -> 상(행감소)
x -> -2, y -> -1 
대각선(열감소, 행감소) -> 좌(열감소)
x -> -1, y -> -2

2. 오른쪽상단
대각선(열증가, 행감소) -> 상(행감소)
x -> -2, y -> +1 
대각선(열증가, 행감소) -> 우(열증가)
x -> -1, y -> +2

3. 왼쪽하단
대각선(열감소, 행증가) -> 좌(열감소)
x -> +1, y -> -2 
대각선(열감소, 행증가) -> 하(행증가)
x -> +2, y -> -1   

4. 오른쪽하단
대각선(열증가, 행증가) -> 우(열증가)
x -> +1, y -> +2 
대각선(열증가, 행증가) -> 하(행증가)
x -> +2, y -> +1

총 8가지 방향을 배열형태로 만듬 
int dx[8] = {-2, -1, -2, -1, 1, 2, 1, 2}
int dy[8] = {-1, -2, 1, 2, -2, -1, 2, 1}

2. 8가지 방향을 다 도는 도중에 해당 지점이 방문한 곳이 아니(dist가 0인 경우)라면 거리를 증가시킴
dist[x][y] = dist[cur.X][cur.Y] + 1;

 

코드

#include<iostream>
#include<queue>	
using namespace std;

int dist[301][301];

// 나이트가 이동할 수 있는 모든 방향
int dx[8] = { -2, -1, -2, -1, 1, 2, 1, 2 };
int dy[8] = { -1, -2, 1, 2, -2, -1, 2, 1 };

int main(void) {
	ios_base::sync_with_stdio(0);
	cin.tie(0);

	// 1.입력
	int T;
	cin >> T;

	for (int i = 0; i < T; i++) {
		int size;
		int startPtX, startPtY; 
		int	endPtX, endPtY;
		cin >> size;
		cin >> startPtX >> startPtY;
		cin >> endPtX >> endPtY;
		
		// 2.로직
		// dist 초기화 
		for (int a = 0; a < size; a++) {
			for (int b = 0; b < size; b++) {
				dist[a][b] = 0;
			}
		}

		queue<pair<int, int>> Q;
		dist[startPtX][startPtY] = 1;
		Q.push({ startPtX, startPtY });
		while (!Q.empty()) {
			pair<int, int> cur = Q.front();
			Q.pop();

			int nx, ny;
			for (int dir = 0; dir < 8; dir++) {
				nx = cur.first + dx[dir];
				ny = cur.second + dy[dir];

				// 범위, 방문여부 체크
				if (nx < 0 || nx >= size || ny < 0 || ny >= size) continue;
				if (dist[nx][ny] > 0) continue;

				dist[nx][ny] = dist[cur.first][cur.second] + 1;
				Q.push({ nx, ny });
			}
		}

		// 3.결과
		cout << dist[endPtX][endPtY] - 1 << "\n";
	}


	return 0;
}


코드 재풀이

#include<iostream>	
#include<queue>
using namespace std;

int vis[301][301];
// 좌상2, 좌하2, 우상2, 우하2
int dx[8] = { -1,-2,1,2,-2,-1,2,1 };
int dy[8] = { -2,-1,-2,-1,1,2,1,2 };
int I;


int main(void) {
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	
	int t;
	cin >> t;
	queue<pair<int, int>> Q;
	while (t--) {
		cin >> I;
		int curNightPosX;
		int curNightPosY;
		int moveNightPosX;
		int moveNightPosY;
		cin >> curNightPosX >> curNightPosY;
		cin >> moveNightPosX >> moveNightPosY;

		// 초기화
		for (int i = 0; i < I; i++) {
			for (int j = 0; j < I; j++) {
				vis[i][j] = 0;
			}
		}

		vis[curNightPosX][curNightPosY] = 1;
		Q.push({ curNightPosX, curNightPosY });
		while (!Q.empty()) {
			pair<int, int> cur = Q.front(); Q.pop();

			if (cur.first == moveNightPosX && cur.second == moveNightPosY) {
				cout << vis[moveNightPosX][moveNightPosY] - 1 << '\n';
				break;
			}

			for (int dir = 0; dir < 8; dir++) {
				int nx = cur.first + dir[dx];
				int ny = cur.second + dir[dy];
				if (nx < 0 || nx >= I || ny < 0 || ny >= I) continue;
				if (vis[nx][ny] >= 1) continue;
				vis[nx][ny] = vis[cur.first][cur.second] + 1;
				Q.push({ nx, ny });
			}
		}
	}	
		
	return 0;
}

 

나이트가 이동하려는 칸에 위치할때 최소 이동 횟수를 출력하고 braek를 해서 while문을 탈출하지만, 

이때 Q에 값이 남아있는 경우 다음 테스트 케이스에서 영향을 끼치기 때문에 문제가 생길 수 있다.

Q에 있는 값이 빌때까지 작업을 계속하고 Q가 비게되면 while문을 빠져간 이후 최소 이동 횟수를 출력하는 방식으로 구현해야 함

 

#include<iostream>	
#include<queue>
using namespace std;

int vis[301][301];
// 좌상2, 좌하2, 우상2, 우하2
int dx[8] = { -1,-2,1,2,-2,-1,2,1 };
int dy[8] = { -2,-1,-2,-1,1,2,1,2 };
int I;


int main(void) {
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	
	int t;
	cin >> t;
	queue<pair<int, int>> Q;
	while (t--) {
		cin >> I;
		int curNightPosX;
		int curNightPosY;
		int moveNightPosX;
		int moveNightPosY;
		cin >> curNightPosX >> curNightPosY;
		cin >> moveNightPosX >> moveNightPosY;

		// 초기화
		for (int i = 0; i < I; i++) {
			for (int j = 0; j < I; j++) {
				vis[i][j] = 0;
			}
		}

		vis[curNightPosX][curNightPosY] = 1;
		Q.push({ curNightPosX, curNightPosY });
		while (!Q.empty()) {
			pair<int, int> cur = Q.front(); Q.pop();			
			for (int dir = 0; dir < 8; dir++) {
				int nx = cur.first + dir[dx];
				int ny = cur.second + dir[dy];
				if (nx < 0 || nx >= I || ny < 0 || ny >= I) continue;
				if (vis[nx][ny] >= 1) continue;
				vis[nx][ny] = vis[cur.first][cur.second] + 1;
				Q.push({ nx, ny });
			}
		}
		
		cout << vis[moveNightPosX][moveNightPosY] - 1 << '\n';
	}	
		
	return 0;
}













 

'알고리즘&자료구조 > BFS' 카테고리의 다른 글

프로그래머스 - 게임 맵 최단거리  (0) 2024.06.05
백준 5427  (1) 2024.05.01
백준 7569  (1) 2024.04.28
백준 10026  (2) 2024.04.27
백준 1012  (2) 2024.04.26