八数码问题:编号为1~8的8个正方形滑块被摆成3行3列(有一个格子留空),如图7-
14所示。每次可以把与空格相邻的滑块(有公共边才算相邻)移到空格中,而它原来的位置就成为了新的空格。给定初始局面和目标局面(用0表示空格),你的任务是计算出最少的移动步数。如果无法到达目标局面,则输出-1。
路径寻找问题可以归结为隐式图的遍历,它的任务是找到一条从初始状态到终止状态的最优路径,而不是像回溯法那样找到一个符合某些要求的解。
#include<iostream>
#include<iomanip>
#include<set>
#include<queue>
#include<map>
using namespace std;
//使用直接哈希的状态数组来判重
//广度用队列
//深度用递归
set<int> vis;
queue<int> que;
//打印路径需要一个状态空间大小的数组记录父亲
int end = 815736402;
bool dowork(int number){
if(number == end) return true;
if(0 == vis.count(number)){
que.push(number);
vis.insert(number);
}
return false;
}
bool bfs(int number){
int init = number;
cout <<number<<"\n";
int s[5][5] = {};
s[1][1] = number/100000000;
s[1][2] = number/10000000%10;
s[1][3] = number/1000000%10;
s[2][1] = number/100000%10;
s[2][2] = number/10000%10;
s[2][3] = number/1000%10;
s[3][1] = number/100%10;
s[3][2] = number/10%10;
s[3][3] = number/1%10;
for(int i=1;i<=3;i++){
for(int j=1;j<=3;j++){
if(s[i][j] == 0 ){
s[i][j] = s[i-1][j];
s[i-1][j] = 0;
number = s[1][1]*100000000 +s[1][2]*10000000 +s[1][3]*1000000
+s[2][1]*100000 +s[2][2]*10000 +s[2][3]*1000
+s[3][1]*100 +s[3][2]*10 +s[3][3]*1;
if(dowork(number)) return true;
s[i-1][j] = s[i][j];
s[i][j] = 0;
s[i][j] = s[i+1][j];
s[i+1][j] = 0;
number = s[1][1]*100000000 +s[1][2]*10000000 +s[1][3]*1000000
+s[2][1]*100000 +s[2][2]*10000 +s[2][3]*1000
+s[3][1]*100 +s[3][2]*10 +s[3][3]*1;
if(dowork(number)) return true;
s[i+1][j] = s[i][j];
s[i][j] = 0;
s[i][j] = s[i][j-1];
s[i][j-1] = 0;
number = s[1][1]*100000000 +s[1][2]*10000000 +s[1][3]*1000000
+s[2][1]*100000 +s[2][2]*10000 +s[2][3]*1000
+s[3][1]*100 +s[3][2]*10 +s[3][3]*1;
if(dowork(number)) return true;
s[i][j-1] = s[i][j];
s[i][j] = 0;
s[i][j] = s[i][j+1];
s[i][j+1] = 0;
number = s[1][1]*100000000 +s[1][2]*10000000 +s[1][3]*1000000
+s[2][1]*100000 +s[2][2]*10000 +s[2][3]*1000
+s[3][1]*100 +s[3][2]*10 +s[3][3]*1;
if(dowork(number)) return true;
s[i][j+1] = s[i][j];
s[i][j] = 0;
return false;
}
}
}
}
int main(){
vis.clear();
freopen("eightNumberQuestion.in","r",stdin);
freopen("eightNumberQuestion.out","w",stdout);
int s[5][5] = {};
cin >>s[1][1]>> s[1][2]>> s[1][3];
cin >>s[2][1]>> s[2][2]>> s[2][3];
cin >>s[3][1]>> s[3][2]>> s[3][3];
int number = s[1][1]*100000000 +s[1][2]*10000000 +s[1][3]*1000000
+s[2][1]*100000 +s[2][2]*10000 +s[2][3]*1000
+s[3][1]*100 +s[3][2]*10 +s[3][3]*1;
que.push(number);
while(!que.empty()){
number = que.front();
que.pop();
if(bfs(number)) break;
}
cout << "true";
fclose(stdin);
fclose(stdout);
}
输出文件略大。