题意:八数码问题,多组输入,给出路径;
分析:因为多组输入而且要给出路径,所以得预先反向BFS把所有结果打表,不然会T ,然后hash就用康托展开;
代码:
#include<queue>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int r[]={1,-1,0,0},c[]={0,0,1,-1};
char kkk[]="udlr"; //因为是反向BFS,所以方向是反着来的
string s;
int Hash[10];
bool vis[400000];
string ANS[400000]; //打表结果
struct node{
string s; //s是当前八数码的状态,step是当前状态走到终点的路径
string step;
node(){}
node(string _s,string _step){
s=_s,step=_step;
}
};
int solve(string s){ //康托展开
int sum=0;
for(int i=0;i<9;i++){
int num=0;
for(int j=i+1;j<9;j++)
if(s[j]<s[i])
num++;
sum+=(num*Hash[9-i-1]);
}
return sum+1;
}
void BFS(){
Hash[0]=1;
for(int i=1;i<10;i++) Hash[i]=Hash[i-1]*i;
string ss="123456780";
vis[solve(ss)]=1;
queue<node>que;
que.push(node(ss,""));
while(!que.empty()){
node top=que.front(); que.pop();
int x,y;
char a[3][3]; int cnt=0;
for(int i=0;i<3;i++)
for(int j=0;j<3;j++){
a[i][j]=top.s[cnt++];
if(a[i][j]=='0'){
x=i,y=j;
}
}
for(int i=0;i<4;i++){
int xx=x+r[i],yy=y+c[i];
if(xx<0||xx>2||yy<0||yy>2) continue;
string op=top.s;
swap(op[x*3+y],op[xx*3+yy]);
int num=solve(op);
if(vis[num]==0){
vis[num]=1;
ANS[num]=kkk[i]+top.step;
que.push(node(op,ANS[num]));
}
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
BFS();
string S;
while(getline(cin,S)){
if(S.length()==0) break;
s.clear();
for(int i=0;i<S.length();i++){
if(S[i]!=' '){
if(S[i]=='x') S[i]='0';
s.push_back(S[i]);
}
}
int ans=solve(s);
if(vis[ans]){
cout<<ANS[ans]<<'\n';
}
else{
cout<<"unsolvable\n";
}
}
}