洛谷 P1379 八数码难题

Description

洛谷传送门

Solution

似乎各种做法都可以过,我写的 \(IDA^*\)

很明显,乐观估价函数即为当前棋盘与目标棋盘上不同的数字个数。

所以直接枚举深搜层数,然后搜索即可。

\(IDA^*\) 的主要难度就在乐观估价函数上,这个弄明白之后,就很简单了。

然后这个写法上面还有一点问题,总之背过板子就好。

另外,还要加一个剪枝:不能走向上一个格子。

简单来说就是不能来回走。这个把方向数组构造一下,然后判断一下即可,见代码。

其他的就没什么了。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>

using namespace std;

int a[5][5];
int b[4][4] = {
	0, 0, 0, 0,
	0, 1, 2, 3,
	0, 8, 0, 4,
	0, 7, 6, 5
};
int tmp, ans, flag;
int dx[4] = {-1, 0, 0, 1};
int dy[4] = {0, -1, 1, 0};
//上左右下

inline int check(){
	int res = 0;
	for(int i = 1; i <= 3; i++)
		for(int j = 1; j <= 3; j++)
			res += (a[i][j] != b[i][j]);
	return res;
}

inline void dfs(int x, int y, int step, int pre){
	if(step == tmp){
		if(!check()) flag = 1;
		return;
	}
	if(flag) return;
	for(int i = 0; i < 4; i++){
		int mx = x + dx[i];
		int my = y + dy[i];
		if(mx < 1 || mx > 3 || my < 1 || my > 3 || i + pre == 3) continue;
		swap(a[x][y], a[mx][my]);
		if(!flag && check() + step <= tmp) dfs(mx, my, step + 1, i);
		swap(a[x][y], a[mx][my]);
	}
}

int main(){
	int x, y;
	for(int i = 1; i <= 3; i++)
		for(int j = 1; j <= 3; j++){
			char c = getchar();
			if(c == '0') x = i, y = j;
			a[i][j] = c - '0';
		}
	if(!check()){
		puts("0");
		return 0;
	}
	for(tmp = 1; ; tmp++){
		dfs(x, y, 0, -1);
		if(flag){
			printf("%d\n", tmp);
			return 0;
		}
	}
	return 0;
}

End

posted @ 2021-10-08 18:50  xixike  阅读(50)  评论(0编辑  收藏  举报