알고리즘/백준

[백준/BOJ/16959] 체스판 여행1

코딩하는 회사원 2024. 3. 26. 23:24
728x90

드러운 문제다.

 

bfs 에 4가지 경우를 넣는다.

1. 체스말 교체

2. 룩의 모든 경우의 수

3. 나이트의 모든 경우의 수

4. 비숍의 모든 경우의 수

 

그리고 num == N*N-1 은, map 에 쓰인 값을 -1 로 처리 했기 때문에 N*N 이 아닌 N*N -1 이 최종 지점이고,

최종 지점에서는 더 할게 없기 때문에 저렇게 처리한다.

#include <iostream>
#include <cstring>
#include <tuple>
#include <queue>
using namespace std;
typedef tuple<int, int, int, int> tp;
const int dx1[] = { -2,-1,1,2,2,1,-1,-2 };
const int dy1[] = { 1,2,2,1,-1,-2,-2,-1 };
const int dx2[] = { 0,0,1,-1 };
const int dy2[] = { 1,-1,0,0 };
const int dx3[] = { 1,1,-1,-1 };
const int dy3[] = { 1,-1,1,-1 };
int N, map[11][11], dp[11][11][101][4];
queue<tp> q;
int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);
	cin >> N;
	memset(dp, -1, sizeof(dp));
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			cin >> map[i][j];
			map[i][j] -= 1;
			if (map[i][j] == 0) {
				for (int k = 0; k < 3; k++) {
					dp[i][j][0][k] = 0;
					q.push({ i,j,0,k });
				}
			}
		}
	}
	int res = -1;
	while (!q.empty()) {
		int x, y, num, piece;
		tie(x, y, num, piece) = q.front(); q.pop();
		if (num == N * N -1) { // 끝에 도달, 더 할게 없다.
			if (res == -1 || res > dp[x][y][num][piece]) {
				res = dp[x][y][num][piece];
			}
		}
		for (int i = 0; i < 3; i++) {
			if (piece == i) continue;
			if (dp[x][y][num][i] == -1) {
				dp[x][y][num][i] = dp[x][y][num][piece] + 1;
				q.push({ x,y,num,i });
				// 교체
			}
		}
		if (piece == 0) {
			for (int i = 0; i < 8; i++) {
				int nx = x + dx1[i];
				int ny = y + dy1[i];
				if (0 <= nx && nx < N && 0 <= ny && ny < N) {
					int next = num;
					if (map[nx][ny] == num + 1) {
						next = num + 1;
					}
					if (dp[nx][ny][next][piece] == -1) {
						dp[nx][ny][next][piece] = dp[x][y][num][piece] + 1;
						q.push({ nx,ny,next,piece });
					}
				}
			}
		}
		else if (piece == 1) {
			for (int i = 0; i < 4; i++) {
				for (int l = 1;; l++) {
					int nx = x + dx2[i] * l;
					int ny = y + dy2[i] * l;
					if (0 <= nx && nx < N && 0 <= ny && ny < N) {
						int next = num;
						if (map[nx][ny] == num + 1) {
							next = num + 1;
						}
						if (dp[nx][ny][next][piece] == -1) {
							dp[nx][ny][next][piece] = dp[x][y][num][piece] + 1;
							q.push({ nx,ny,next,piece });
						}
					}
					else {
						break;
					}
				}
			}
		}
		else {
			for (int i = 0; i < 4; i++) {
				for (int l = 1;; l++) {
					int nx = x + dx3[i] * l;
					int ny = y + dy3[i] * l;
					if (0 <= nx && nx < N && 0 <= ny && ny < N) {
						int next = num;
						if (map[nx][ny] == num + 1) {
							next = num + 1;
						}
						if (dp[nx][ny][next][piece] == -1) {
							dp[nx][ny][next][piece] = dp[x][y][num][piece] + 1;
							q.push({ nx,ny,next,piece });
						}
					}
					else {
						break;
					}
				}
			}
		}
	}
	cout << res << "\n";
	return 0;
}
728x90