在成功地發明了魔方以後,魯比克先生髮明瞭它的二維版本,稱做魔板。這是一張有8個大小相同的格子的魔板:c++
1 2 3 4 8 7 6 5
咱們知道魔板的每個方格都有一種顏色。這8種顏色用前8個正整數來表示。能夠用顏色的序列來表示一種魔板狀態,規定從魔板的左上角開始,沿順時針方向依次取出整數,構成一個顏色序列。對於上圖的魔板狀態,咱們用序列(1,2,3,4,5,6,7,8)來表示。這是基本狀態。編程
這裏提供三種基本操做,分別用大寫字母「A」,「B」,「C」來表示(能夠經過這些操做改變魔板的狀態):數組
「A」:交換上下兩行;框架
「B」:將最右邊的一列插入最左邊;函數
「C」:魔板中央四格做順時針旋轉。spa
下面是對基本狀態進行操做的示範:code
A: 8 7 6 5 1 2 3 4 B: 4 1 2 3 5 8 7 6 C: 1 7 2 4 8 6 3 5
對於每種可能的狀態,這三種基本操做均可以使用。遞歸
你要編程計算用最少的基本操做完成基本狀態到目標狀態的轉換,輸出基本操做序列。內存
輸入格式:字符串
只有一行,包括8個整數,用空格分開(這些整數在範圍 1——8 之間)不換行,表示目標狀態。
輸出格式:
Line 1: 包括一個整數,表示最短操做序列的長度。
Line 2: 在字典序中最先出現的操做序列,用字符串表示,除最後一行外,每行輸出60個字符。
2 6 8 4 5 7 3 1
7 BCABCCB
衆所周知,這是一道廣搜題,那麼本題的大致思路就明確了,剩下的就是耐心地解決一些細節問題。
魔板本來是2X4的矩陣,但一維處理起來必定比二維方便,因而即可以降維,但,要注意技巧。
以樣例來講,括號裏面表明這個數儲存的一維數組的位置
2(a1) | 6(a2) | 8(a3) | 4(a4) |
5(a5) | 7(a6) | 3(a7) | 1(a8) |
具體實現請看代碼:
for(int i=1;i<=8;i++){//基本狀態 if(i<=4) sak[1].before[i]=i; if(i>4) sak[1].before[i]=13-i; }
for(int i=1;i<=4;i++)//雙循環輸入目標狀態(真~~樸素~~) scanf("%d",&after[i]); for(int i=8;i>=5;i--) scanf("%d",&after[i]);
8個數排列組合必定,因此只須要斷定前七個數就必定能知道最後一個數,這樣就不會超出內存限制啦。而後用標記數組給這個七位數打個標記。
int pan(int a[]){//自定義pan函數用來判重 int ans=0; for(int i=7;i>=1;i--) ans=ans*10+a[i]; return ans; }
無腦模擬。
AC代碼
#include <bits/stdc++.h> using namespace std; int after[9],ans,o,jishu;//after數組爲目標狀態,o和jishu爲累加器輔助判斷一些奇怪的東西 bool fla[9000005],k; struct sakura{//結構體 int before[9],f;char step; }sak[100086]; int pan(int a[]){//自定義pan函數用來判重 int ans=0; for(int i=7;i>=1;i--) ans=ans*10+a[i]; return ans; } bool judge(int a[]){ for(int i=1;i<=8;i++) if(a[i]!=after[i]) return 0; return 1; } void print(int a){//遞歸輸出 if(sak[a].f!=0){ o++; print(sak[a].f); } if(!sak[a].f) return; if(!k){//輸出步數 printf("%d\n",o); k=1; } printf("%c",sak[a].step); jishu++; if(!jishu%60)//隔60個換行 printf("\n"); } void bfs(){ int h=0,t=1;sak[t].f=0; while(h<t){ h++; for(int i=1;i<=3;i++){//保證框架完整 int bit[9]; if(i==1){//A操做 for(int i=1;i<=4;i++){ bit[i]=sak[h].before[i+4]; bit[i+4]=sak[h].before[i]; } } if(i==2){//B操做 bit[1]=sak[h].before[4];bit[5]=sak[h].before[8]; bit[2]=sak[h].before[1];bit[6]=sak[h].before[5]; bit[3]=sak[h].before[2];bit[7]=sak[h].before[6]; bit[4]=sak[h].before[3];bit[8]=sak[h].before[7]; } if(i==3){//C操做 bit[1]=sak[h].before[1]; bit[2]=sak[h].before[6]; bit[3]=sak[h].before[2]; bit[4]=sak[h].before[4]; bit[5]=sak[h].before[5]; bit[8]=sak[h].before[8]; bit[7]=sak[h].before[3]; bit[6]=sak[h].before[7]; } if(!fla[pan(bit)]){ t++; if(i==1) sak[t].step='A'; if(i==2) sak[t].step='B'; if(i==3) sak[t].step='C'; fla[pan(bit)]=1;//標記 sak[t].f=h;//記錄爸爸 for(int i=1;i<=8;i++) sak[t].before[i]=bit[i]; if(ans==pan(bit)){ print(t); exit(0);//萬惡之源結束 } } } } } int main(){ for(int i=1;i<=8;i++){//降維打擊 if(i<=4) sak[1].before[i]=i; if(i>4) sak[1].before[i]=13-i; } fla[pan(sak[1].before)]=1; for(int i=1;i<=4;i++) scanf("%d",&after[i]); for(int i=8;i>=5;i--) scanf("%d",&after[i]); ans=pan(after); if(ans==pan(sak[1].before)){//特判(貌似並不須要) printf("0\n"); return 0; } bfs();//萬惡之源開始 return 0; }