[USACO3.2]Magic Squares 魔板
阿新 • • 發佈:2018-12-30
題目大意
給出一個2*4的矩陣,有3種基本操作
A | B | C |
---|---|---|
交換上下兩行 | 將最右邊的一列插入最左邊 | 中央四格作順時針旋轉 |
基本狀態:
1 2 3 4
8 7 6 5
給定一個目標狀態,求最少的基本操作完成基本狀態到目標狀態的轉換,輸出基本操作序列。
題目解析
該題目很明顯是用搜索做,如果用深搜,則會超時,所以只能用寬搜。
但是如果沒有一種好的方法來判斷是否已經加入列表,可能會超時,所以,雜湊表。
程式碼
#include<iostream> #include<string> #define p 100003//質數 using namespace std; int x,f[p],num[p],head,tail=1;//f標記父節點 num表示當前狀態的最少運算元 int r[3][8]={{8,7,6,5,4,3,2,1},{4,1,2,3,6,7,8,5},{1,7,2,4,5,3,6,8}};//變換的規則 char ans[p];//儲存 A B C string g,a[p],state[p];//g為目標狀態 bool hash(string s)//雜湊函式 { int k=0,i=0; for(int i=0;i<8;i++) k=k*10+s[i]-48; k%=p; while(a[(k+i)%p]!=""&&a[(k+i)%p]!=s) i++; if(a[(i+k)%p]=="") { a[(i+k)%p]=s; return false; } return true; } void bfs() { hash("12345678"); state[1]="12345678";//初始化 do { head++; for(int i=0;i<3;i++) { tail++; f[tail]=head; state[tail]=""; num[tail]=num[head]+1; ans[tail]='A'+i; for(int j=0;j<8;j++) state[tail]+=state[head][r[i][j]-1];//字串從0為開始算 if(hash(state[tail])) tail--;//判斷是否能夠入隊 else if(state[tail]==g) return;//找到目標狀態 } }while(head<tail); } void out(int x)//輸出 { if(x==1) return; out(f[x]); cout<<ans[x]; } int main() { for(int i=1;i<=8;i++) { cin>>x; g+=x+48; }//目標狀態轉換為字串 if(g=="12345678") { cout<<0; return 0; }//特判 bfs();//寬搜 cout<<num[tail]<<endl; out(tail); }