hdu1430 康託展開+bfs預處理
阿新 • • 發佈:2020-07-20
hdu1430 魔板
傳送門
一個含有數字[1,8],兩行四列,具有八個方塊的魔板可以進行三種變換:
A.交換上下兩行
B.迴圈右移一列
C.中間4個方塊順時針旋轉
計算從初始狀態到目標狀態變換次數最小的方法中,字典序最小的那種。
康託展開+bfs預處理
將初始狀態全部對映為"01234567",目標狀態根據相同的對映函式對映成為相應的目標狀態。一次bfs預處理初始狀態為"01234567"的所有可達狀態,記錄每一步的操作。
因為實際移動是方塊之間位置的移動,數字只是一個標號,所以改變數字編號同樣可以表示方塊的位置移動。所以三種操作也可以通過預先設定陣列,記錄編號位置的變化來實現。
#include<iostream> #include<cstdio> #include<vector> #include<stack> #include<queue> #include<set> #include<map> #include<cstring> #include<string> #include<cmath> #include<ctime> #include<algorithm> #include<functional> using namespace std; int fac[10]={1,1,2,6,24,120,720,5040,40320},book[60010]; int change[3][10]={{7,6,5,4,3,2,1,0},{3,0,1,2,5,6,7,4},{0,6,1,3,4,2,5,7}}; char s[10],t[10],g[10]; string ans[60010]; struct node{ char str[8]; }; int cantor(char* a){ int cnt,hash=0; for(int i=0;i<8;i++){ cnt=0; for(int j=i+1;j<8;j++){ if(a[j]<a[i]) cnt++; } hash+=cnt*fac[8-i-1]; } return hash; } void bfs(){ queue<node> q; node t1,t2; for(int i=0;i<8;i++) t1.str[i]=i+'0'; int hash=cantor(t1.str); q.push(t1); book[hash]=1; while(!q.empty()){ t1=q.front(); q.pop(); int h1=cantor(t1.str); for(int i=0;i<3;i++){ for(int j=0;j<8;j++){ t2.str[j]=t1.str[change[i][j]]; } int h2=cantor(t2.str); if(book[h2]) continue; book[h2]=1; ans[h2]=ans[h1]+(char)(i+'A'); q.push(t2); } } } int main(void){ ios::sync_with_stdio(false); bfs(); while(cin>>s>>t){ for(int i=0;i<8;i++) g[s[i]-'0']=i; for(int i=0;i<8;i++) t[i]=g[t[i]-'0']; cout<<ans[cantor(t)]<<"\n"; } return 0; }