首页 > 代码库 > 【USACO 3.2.5】魔板

【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 }