[bzoj 1331]魔板
Description
在成功地發明了魔方之後,魯比克先生發明了它的二維版本,稱作魔板。這是一張有8個大小相同的格子的魔板:
|1|2|3|4|
|-|-|-|-|
|8|7|6|5|
我們知道魔板的每一個方格都有一種顏色。這8種顏色用前8個正整數來表示。可以用顏色的序列來表示一種魔板狀態,規定從魔板的左上角開始,沿順時針方向依次取出整數,構成一個顏色序列。對於上圖的魔板狀態,我們用序列(1,2,3,4,5,6,7,8)來表示。這是基本狀態。這裏提供三種基本操作,分別用大寫字母“A”,“B”,“C”來表示(可以通過這些操作改變魔板的狀態):
- “A”:交換上下兩行;
- “B”:將最右邊的一列插入最左邊;
- “C”:魔板中央四格作順時針旋轉。
下面是對基本狀態進行操作的示範:
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|
對於每種可能的狀態,這三種基本操作都可以使用。
你要編程計算用最少的基本操作完成基本狀態到目標狀態的轉換,輸出基本操作序列。
Input
只有一行,包括8個整數,用空格分開(這些整數在範圍 1——8 之間)不換行,表示目標狀態。
Output
Line 1: 包括一個整數,表示最短操作序列的長度。
Line 2: 在字典序中最早出現的操作序列,用字符串表示,除最後一行外,每行輸出60個字符。
Sample Input
2 6 8 4 5 7 3 1
Sample Output
7
BCABCCB
直接上BFS,然後狀態的話,用個struct存下這8個數的狀態,狀態的存法決定了轉移方法。然後判斷是否走過,用map,然後發現只要判斷是否出現,那不如用下C++11的騷操作 unordered_set,學會了手打hash函數。。。否則這東西不能扔struct。。。
/*program from Wolfycz*/ #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<unordered_set> #define inf 0x7f7f7f7f using namespace std; typedef long long ll; typedef unsigned int ui; typedef unsigned long long ull; inline int read(){ int x=0,f=1;char ch=getchar(); for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1; for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+ch-'0'; return x*f; } inline void print(int x){ if (x>=10) print(x/10); putchar(x%10+'0'); } const int N=5e4; const char s[3]={'A','B','C'}; const int T[3][8]={ {7,6,5,4,3,2,1,0}, {1,2,3,0,7,4,5,6}, {0,2,5,3,4,6,1,7}, }; struct S1{ int val[8]; bool operator ==(const S1 &x)const{ for (int i=0;i<8;i++) if (val[i]!=x.val[i]) return 0; return 1; } }h[N+10],tmp,Endl; struct myHash{ size_t operator ()(const S1 &x)const{ int res=0; for (int i=0;i<8;i++) res=(res<<3)+(res<<1)+x.val[i]; return(res); } }; int dis[N+10],opera[N+10],from[N+10]; unordered_set<S1,myHash>st; int bfs(){ int head=1,tail=1; for (int i=0;i<8;i++) h[head].val[i]=i+1; if (Endl==h[head]) return head; st.insert(h[head]),dis[head]=0; for (;head<=tail;head++){ for (int k=0;k<3;k++){ for (int i=0;i<8;i++) tmp.val[T[k][i]]=h[head].val[i]; if (!st.count(tmp)){ st.insert(h[++tail]=tmp); dis[tail]=dis[head]+1; from[tail]=head; opera[tail]=k; if (tmp==Endl) return tail; } } } return 0; } int stack[N+10]; int main(){ for (int i=0;i<8;i++) Endl.val[i]=read(); int T=bfs(),top=0,cnt=0; printf("%d\n",dis[T]); while (T!=1) stack[++top]=opera[T],T=from[T]; for (int i=top;i;i--){ printf("%c",s[stack[i]]),cnt++; if (cnt==60){ putchar('\n'); cnt=0; } } return 0; }
[bzoj 1331]魔板