魔板 Magic Squares(廣搜,狀態轉化)
題目背景
在成功地發明了魔方之後,魯比克先生發明了它的二維版本,稱作魔板。這是一張有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
對於每種可能的狀態,這三種基本操作都可以使用。
你要編程計算用最少的基本操作完成基本狀態到目標狀態的轉換,輸出基本操作序列。
輸入輸出格式
輸入格式:
只有一行,包括8個整數,用空格分開(這些整數在範圍 1——8 之間)不換行,表示目標狀態。
輸出格式:
Line 1: 包括一個整數,表示最短操作序列的長度。
Line 2: 在字典序中最早出現的操作序列,用字符串表示,除最後一行外,每行輸出60個字符。
思路:
廣搜應該大家都知道,但是狀態怎麽存?(8^8的數組絕對爆空間)
(大佬:康拓展開)
我不會啊qwq
沒辦法嘍,只能從排列數來看
8!,空間裝得下
那麽我們就該想一下怎麽算位置了
比如說一個狀態
4 1 2 3
8 5 6 7
我們按著行來算,化成一個數字
41238567
在這個數據前有多少個排列呢?
我們一位一位看
首先,看第一位
此時沒有用過且比4小的數有1 2 3 三個
所以就有7!*3個數在他前面
再看第二位
沒有比他小的數,跳過
一位一位地算,就可以知道有多少個比他小的排列
最後+1,就是編號嘍
需要調換的時候編號轉狀態是同理的
廣搜就好嘍
註意:他的數據為順時針給出,我的程序為按行讀入
所以初始狀態1 2 3 4 5 6 7 8
在我這裏的映射為
1 2 3 4
8 7 6 5
代碼:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define rii register int i #define rij register int j using namespace std; bool bj[40325]; int n; struct que{ int zt,sd,pre,cz; }q[40325]; int st,jc[10]={0,1,2,6,24,120,720,5040,40320},cnt; int ans[100005]; int change(int xl) { int mc=1; int ls[10]={0,0,0,0,0,0,0,0,0,0}; int sy[10]={0,0,0,0,0,0,0,0,0,0}; for(rii=8;i>=1;i--) { ls[i]=xl%10; xl/=10; } for(rii=1;i<=7;i++) { int ltt=ls[i]; for(rij=1;j<=ltt-1;j++) { if(sy[j]!=1) { mc+=jc[8-i]; } } sy[ltt]=1; } return mc; } void add(int bh,int pre,int cz) { cnt++; q[cnt].cz=cz; q[cnt].pre=pre; q[cnt].zt=bh; q[cnt].sd=q[pre].sd+1; } void A(int bh,int pre) { bh--; int ls[10]={0,0,0,0,0,0,0,0,0,0}; int sy[10]={0,0,0,0,0,0,0,0,0,0}; for(rii=1;i<=7;i++) { int ltt=bh/jc[8-i]; bh-=ltt*jc[8-i]; int sl=0; for(rij=1;j<=8;j++) { if(sy[j]!=1) { sl++; } if(sl==ltt+1) { sy[j]=1; ls[i]=j; break; } } } for(rii=1;i<=8;i++) { if(sy[i]==0) { ls[8]=i; break; } } memset(sy,0,sizeof(sy)); for(rii=1;i<=4;i++) { int kkk=ls[i]; ls[i]=ls[i+4]; ls[i+4]=kkk; } int mc=1; for(rii=1;i<=7;i++) { int ltt=ls[i]; for(rij=1;j<=ltt-1;j++) { if(sy[j]!=1) { mc+=jc[8-i]; } } sy[ltt]=1; } if(bj[mc]!=1) { add(mc,pre,1); bj[mc]=1; } } void B(int bh,int pre) { bh--; int ls[10]={0,0,0,0,0,0,0,0,0,0}; int sy[10]={0,0,0,0,0,0,0,0,0,0}; for(rii=1;i<=7;i++) { int ltt=bh/jc[8-i]; bh-=ltt*jc[8-i]; int sl=0; for(rij=1;j<=8;j++) { if(sy[j]!=1) { sl++; } if(sl==ltt+1) { sy[j]=1; ls[i]=j; break; } } } for(rii=1;i<=8;i++) { if(sy[i]==0) { ls[8]=i; break; } } memset(sy,0,sizeof(sy)); int a1=ls[4]; int b1=ls[8]; for(rii=4;i>=2;i--) { ls[i]=ls[i-1]; ls[i+4]=ls[i+3]; } ls[1]=a1; ls[5]=b1; int mc=1; for(rii=1;i<=7;i++) { int ltt=ls[i]; for(rij=1;j<=ltt-1;j++) { if(sy[j]!=1) { mc+=jc[8-i]; } } sy[ltt]=1; } if(bj[mc]!=1) { add(mc,pre,2); bj[mc]=1; } } void output(int fi) { int len=q[fi].sd; printf("%d\n",len); int wz=fi; for(rii=len;i>=1;i--) { ans[i]=q[wz].cz; wz=q[wz].pre; } int cnt=0; for(rii=1;i<=len;i++) { if(ans[i]==1) { putchar(‘A‘); continue; } if(ans[i]==2) { putchar(‘B‘); continue; } else { putchar(‘C‘); } cnt++; if(cnt==60) { puts(""); cnt=0; } } } void C(int bh,int pre) { bh--; int ls[10]={0,0,0,0,0,0,0,0,0,0}; int sy[10]={0,0,0,0,0,0,0,0,0,0}; for(rii=1;i<=7;i++) { int ltt=bh/jc[8-i]; bh-=ltt*jc[8-i]; int sl=0; for(rij=1;j<=8;j++) { if(sy[j]!=1) { sl++; } if(sl==ltt+1) { sy[j]=1; ls[i]=j; break; } } } for(rii=1;i<=8;i++) { if(sy[i]==0) { ls[8]=i; break; } } memset(sy,0,sizeof(sy)); int a2=ls[2],a3=ls[3],b2=ls[6],b3=ls[7]; ls[3]=a2; ls[2]=b2; ls[6]=b3; ls[7]=a3; int mc=1; for(rii=1;i<=7;i++) { int ltt=ls[i]; for(rij=1;j<=ltt-1;j++) { if(sy[j]!=1) { mc+=jc[8-i]; } } sy[ltt]=1; } if(bj[mc]!=1) { add(mc,pre,3); } bj[mc]=1; } int main() { scanf("%d",&st); for(rii=2;i<=4;i++) { int ltt; st*=10; scanf("%d",<t); st+=ltt; } st*=10000; int sr; scanf("%d",&sr); st+=sr; scanf("%d",&sr); st+=sr*10; scanf("%d",&sr); st+=sr*100; scanf("%d",&sr); st+=sr*1000; int fi=change(st); q[1].zt=24; bj[24]=1; cnt=1; for(rii=1;i<=cnt;i++) { int z=q[i].zt; if(z==fi) { output(i); return 0; } A(z,i); B(z,i); C(z,i); } }
魔板 Magic Squares(廣搜,狀態轉化)