原題鏈接:Here!
分析:求經過若干次四個操作 ' r ' , ' l ' , ' u ' , ' d ' 到狀態1 2 3 4 5 6 7 8 x,輸出操作順序。因爲最終狀態一定,所以採用反向BFS打表,記錄路徑即可。
CODE:
/*
Note:
因爲題目要求是任意狀態求是否能到一個"完美狀態",因爲任意狀態不確定性和完美狀態的確定性,所以不妨
反向BFS+打表
摳腳
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<queue>
using namespace std;
#define test
int fac[]={1,1,2,6,24,120,720,5040,40320,362880};
int Cantor(int *s,int n){ // 康託展開
int ans=0;
for(int i=0;i<n;i++){
int tmp=0;
for(int j=i+1;j<n;j++)
if(s[i]>s[j]) tmp++;
ans += tmp*fac[n-1-i];
}
return ans;
}
void unCantor(int index,int *t,int n){ // 康託逆展開
index--;
int i,j;
int vis[10]={0};
for(i=0;i<n;i++){
int tmp=index/fac[n-1-i];
for(j=0;j<=tmp;j++)
if(vis[j]) tmp++;
t[i]=tmp+1;
vis[tmp]=1;
index%=fac[n-1-i];
}
}
const int maxn = 362880; // 9! = 362880
bool can[maxn]; // 記錄狀態是否出現
char ans[maxn][42]; // 打個表將答案打到一個二維數組中,第一維是Cantor值,然後是一個字符串
int target[]={1,2,3,4,5,6,7,8,0}; // 目標狀態
int tt[9];
struct Node{ // Node的信息代表 key是空白點在(x,y)的狀態下的康託值,tol是拓展層數
int key,x,y,tol;
Node(int _key,int _x,int _y,int _tol):key(_key),x(_x),y(_y),tol(_tol){}
};
queue<Node> q;
void bfs(){
// 初始化
memset(can,false,sizeof(can));
while(!q.empty()) q.pop();
int t_key=Cantor(target,9); // 找到目標狀態康託值
can[t_key]=true;
ans[t_key][0]='\0';
q.push(Node(t_key,2,2,0)); // 3x3 初始點x在(2,2)
while(!q.empty()){
Node tmp=q.front(); q.pop();
unCantor(tmp.key+1,tt,9); // 將Cantor值對應的狀態錄入到數組tt中
int x=tmp.x, y=tmp.y;
// 接下來4個if 代表上下左右走,因爲是倒序BFS所以向上走時就是原來的向下走,其他相同
if(x>=1){ // 倒序向上走
swap(tt[x*3+y],tt[(x-1)*3+y]); // 交換兩個格子
t_key=Cantor(tt,9);
if(!can[t_key]){
q.push(Node(t_key,x-1,y,tmp.tol+1)); // 記錄向上走後的狀態,然後tol+1
can[t_key]=true;
for(int i=0;i<tmp.tol;i++) ans[t_key][i]=ans[tmp.key][i]; // *繼承父親的路徑
ans[t_key][tmp.tol]='d';
ans[t_key][tmp.tol+1]='\0';
}
swap(tt[x*3+y],tt[(x-1)*3+y]); // 爲什麼每次都要交換過來,如果不能交換,當然得保持原樣
}
if(y>=1){ // 倒序向左走
swap(tt[x*3+y],tt[x*3+(y-1)]);
t_key=Cantor(tt,9);
if(!can[t_key]){
q.push(Node(t_key,x,y-1,tmp.tol+1));
can[t_key]=true;
for(int i=0;i<tmp.tol;i++) ans[t_key][i]=ans[tmp.key][i];
ans[t_key][tmp.tol]='r';
ans[t_key][tmp.tol+1]='\0';
}
swap(tt[x*3+y],tt[x*3+(y-1)]);
}
if(x<=1){ // 倒序向下走
swap(tt[x*3+y],tt[(x+1)*3+y]);
t_key=Cantor(tt,9);
if(!can[t_key]){
q.push(Node(t_key,x+1,y,tmp.tol+1));
can[t_key]=true;
for(int i=0;i<tmp.tol;i++) ans[t_key][i]=ans[tmp.key][i];
ans[t_key][tmp.tol]='u';
ans[t_key][tmp.tol+1]='\0';
}
swap(tt[x*3+y],tt[(x+1)*3+y]);
}
if(y<=1){ // 倒序向右走
swap(tt[x*3+y],tt[x*3+(y+1)]);
t_key=Cantor(tt,9);
if(!can[t_key]){
q.push(Node(t_key,x,y+1,tmp.tol+1));
can[t_key]=true;
for(int i=0;i<tmp.tol;i++) ans[t_key][i]=ans[tmp.key][i];
ans[t_key][tmp.tol]='l';
ans[t_key][tmp.tol+1]='\0';
}
swap(tt[x*3+y],tt[x*3+(y+1)]);
}
}
}
int d[9]; // 存放目標狀態
void solve(){
int t_key=Cantor(d,9);
if(!can[t_key]){ printf("unsolvable\n"); return; }
int len=strlen(ans[t_key]);
for(int i=len-1;i>=0;i--)
printf("%c",ans[t_key][i]);
printf("\n");
}
int main(){
bfs(); // 反向BFS打表
#ifdef test
freopen("Hdu 1043 Eight.txt","r",stdin);
#endif
string op;
while(getline(cin,op)){
for(int i=0,j=0;i<op.size();i++){
if(op[i]>='1' && op[i]<='8')
d[j++]=op[i]-'0';
if(op[i]=='x')
d[j++]=0;
}
solve();
}
return 0;
}