【USACO 3.2.5】魔板
【描述】
在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板。这是一张有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
对于每种可能的状态,这三种基本操作都可以使用。
你要编程计算用最少的基本操作完成基本状态到目标状态的转换,输出基本操作序列。
【格式】
PROGRAM NAME: msquare
INPUT FORMAT:
(file msquare.in)
只有一行,包括8个整数,用空格分开(这些整数在范围 1——8 之间)不换行,表示目标状态。
OUTPUT FORMAT:
(file msquare.out)
Line 1: 包括一个整数,表示最短操作序列的长度。
Line 2: 在字典序中最早出现的操作序列,用字符串表示,除最后一行外,每行输出60个字符。
【分析】
直接广搜就行了,然后用哈希判重。
1 #include <cstdlib> 2 #include <iostream> 3 #include <cmath> 4 #include <cstdio> 5 #include <cstring> 6 #include <algorithm> 7 #include <set> 8 #include <queue> 9 #include <vector> 10 using namespace std; 11 struct state 12 { 13 int data[2][5]; 14 int step,parent;//步数 15 int kind;//表示该状态经过哪一种变换得来 16 }begin,end;//ren用来记录标号 17 bool hash[16777216*2]; 18 int sqr[9]; 19 unsigned int point=0,p=0;//rem指针 20 vector<state>Q; 21 22 void bfs(); 23 bool check(state a,state b); 24 void init();//初始化 25 void change(state &t,int type); 26 void print(int t);//打印 27 int h(state t);//哈希函数 28 29 int main() 30 { 31 //文件操作 32 freopen("msquare.in","r",stdin); 33 freopen("msquare.out","w",stdout); 34 //读入与初始化 35 for (int i=1;i<=4;i++) {scanf("%d",&end.data[0][i]);begin.data[0][i]=i;} 36 for (int j=4;j>=1;j--) {scanf("%d",&end.data[1][j]);begin.data[1][j]=8-j+1;} 37 if (check(begin,end)) {printf("0");return 0;} 38 bfs(); int temp=Q.size()-1; 39 printf("%d\n",Q[temp].step); 40 print(temp); 41 return 0; 42 } 43 void init() 44 { 45 memset(hash,0,sizeof(hash)); 46 sqr[0]=1; 47 for (int i=1;i<=7;i++) sqr[i]=sqr[i-1]*8; 48 begin.step=0; 49 begin.parent=-1; 50 } 51 void bfs() 52 { 53 Q.push_back(begin); 54 init(); 55 while (point<Q.size()) 56 { 57 state u=Q[point]; 58 state temp=u;//记录 59 60 for (int i=1;i<=3;i++) 61 { 62 change(u,i); 63 if (hash[h(u)]==0)//没有加入过 64 { 65 Q.push_back(u); 66 hash[h(u)]=1; 67 if (check(u,end)) return; 68 }u=temp;//还原 69 } 70 point++; 71 } 72 } 73 bool check(state a,state b)//比较函数 74 { 75 for (int i=0;i<=1;i++) 76 for (int j=1;j<=4;j++) if (a.data[i][j]!=b.data[i][j]) return 0; 77 return 1; 78 } 79 void change(state &t,int type) 80 { 81 state temp=t; 82 //初始化 83 temp.step++; 84 temp.parent=point; 85 temp.kind=type; 86 if (type==1) for (int i=1;i<=4;i++) swap(temp.data[0][i],temp.data[1][i]); 87 else if (type==2) 88 { 89 temp.data[0][1]=t.data[0][4]; 90 temp.data[1][1]=t.data[1][4]; 91 for (int i=2;i<=4;i++) 92 { 93 temp.data[0][i]=t.data[0][i-1]; 94 temp.data[1][i]=t.data[1][i-1]; 95 } 96 } 97 else if (type==3) 98 { 99 temp.data[0][2]=t.data[1][2]; 100 temp.data[0][3]=t.data[0][2]; 101 temp.data[1][3]=t.data[0][3]; 102 temp.data[1][2]=t.data[1][3]; 103 } 104 t=temp; 105 } 106 void print(int t) 107 { 108 if (!t) return; 109 print(Q[t].parent); 110 printf("%c",char(Q[t].kind-1+'A')); 111 ++p; 112 if (p==60) {printf("\n");p=0;}//换行 113 } 114 int h(state t) 115 { 116 int i,j,ans=0; 117 for (i=0;i<=1;i++) 118 for (j=1;j<=4;j++) ans+=t.data[i][j]*sqr[i*4+j-1]; 119 return ans; 120 }