很经典的一道题,我用的是宽度优先搜索,set判重,本来这题可以用康托展开和逆展开,再开一个大数组,判重可做到O(1)的时间复杂度,这里偷一个懒,直接将数组变成了一个9位数,统统丢set去判重,set查找效率还是很高的,毕竟红黑树,这里还顺便复习了一下结构体的初始化,每个结构体都代表一个状态,每个状态储存着一个9位数,步数,空格位置,似乎每一个都是必须。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<set>
using namespace std;
struct state{
int num;
int step;
int pos;
};
queue<state> Q;
set<int> S;
char ch;
int space,sum,goal=123804765;
int d[4]={-1,1,-3,3},num[9];
int code(){
int t=0;
for(int i=0;i<9;i++){
t=10*t+num[i];
}
return t;
}
int decode(int n){
for(int i=8;i>=0;i--){
num[i]=n%10;
n/=10;
}
}
int main(){
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
for(int i=0;i<9;i++){
cin>>ch;
num[i]=ch-'0';
if (num[i]==0) space=i;
}
state first={code(),0,space};
Q.push(first);
while(!Q.empty()){
state tmp=Q.front();Q.pop();
decode(tmp.num);
for(int i=0;i<4;i++){
if ((i==0)&&(tmp.pos==0||tmp.pos==3||tmp.pos==6)) continue;
if ((i==1)&&(tmp.pos==2||tmp.pos==5||tmp.pos==8)) continue;
if ((i==2)&&(tmp.pos==0||tmp.pos==1||tmp.pos==2)) continue;
if ((i==3)&&(tmp.pos==6||tmp.pos==7||tmp.pos==8)) continue;
swap(num[tmp.pos+d[i]],num[tmp.pos]);
sum=code();
if (sum==goal){
cout<<tmp.step+1<<endl;
return 0;
}
if (S.find(sum)==S.end()){
S.insert(sum);
state tmp1={sum,tmp.step+1,tmp.pos+d[i]};
Q.push(tmp1);
}
swap(num[tmp.pos+d[i]],num[tmp.pos]);
}
}
return 0;
}
这题还可以用A*来做,留个坑,下次填上