原题链接
考察:反向bfs+打表
思路:
可以以终态为起点求能到达的所有状态,并记录路径.这里可以不用unordered_map的记录状态,而是用康拓展开.(详细解释 GO)
注意康拓展开和反康拓展开是返回前面有几个全排列.
不多解释,这篇题解已经很详细了GO
1 #include <unordered_map> 2 #include <iostream> 3 #include <cstring> 4 #include <algorithm> 5 #include <string> 6 #include <queue> 7 using namespace std; 8 const int N = 362890,M = 10; 9 char index[5] = "durl";10 int vis[N],temp[M],b[M];11 int xx[4] = {-1,1,0,0},yy[4] ={0,0,-1,1};12 int factor[12] = {1,1,2,6,24,120,720,5040,40320,362880,3628000};13 unordered_map<int,string> path;14 int cantor(int a[])//康拓展开 15 {16 int sum = 0;17 for(int i=0;i<9;i++)18 {19 int small = 0;20 for(int j=i+1;j<9;j++)21 if(a[i]>a[j]) small++;22 sum+=small*factor[8-i];23 }24 return sum+1;25 }26 void decantor(int a[],int val)27 {28 vector<int> v;29 for(int i=0;i<9;i++) v.push_back(i);30 for(int i=0;i<9;i++)31 {32 int cnt = val/factor[8-i];33 int now = val%factor[8-i];34 val = now;35 sort(v.begin(),v.end());36 a[i] = v[cnt];37 v.erase(v.begin()+cnt);38 }39 }40 int get(int a[])41 {42 for(int i=0;i<9;i++)43 if(a[i]==0) return i;44 return -1;45 }46 void bfs()47 {48 for(int i=0;i<8;i++) temp[i] = i+1;49 temp[8] = 0;50 queue<int> q;51 int vw = cantor(temp);52 q.push(vw);53 path[vw] = "";54 vis[vw] = 1;55 while(q.size())56 {57 int it = q.front();58 q.pop();59 decantor(temp,it-1);60 int pos = get(temp);61 int x = pos/3,y = pos%3;62 // memcpy(b,temp,sizeof b);63 for(int i=0;i<4;i++)64 {65 int dx = x+xx[i],dy = y+yy[i];66 if(dx>=0&&dx<3&&dy>=0&&dy<3)67 {68 int spos = dx*3+dy;69 swap(temp[pos],temp[spos]);70 int val = cantor(temp);71 swap(temp[pos],temp[spos]);72 if(vis[val]) continue;73 vis[val] =1;74 path[val] = index[i]+path[it];75 q.push(val);76 }77 }78 }79 }80 int main()81 {82 bfs();83 string ns;84 while(getline(cin,ns))85 {86 int cnt = 0;87 for(int i=0;i<ns.size();i++)88 if(isalnum(ns[i]))89 {90 if(ns[i]=='x') b[cnt++] = 0;91 else b[cnt++] = ns[i]-'0';92 }93 int val = cantor(b);94 if(!vis[val]) puts("unsolvable");95 else printf("%s\n",path[val].c_str());96 }97 return 0;98 }