HDU_1430——魔板,预处理,康托展开,置换,string类的+操作

Problem Description
在魔方风靡全球之后不久,Rubik先生发明了它的简化版——魔板。魔板由8个同样大小的方块组成,每个方块颜色均不相同,可用数字1-8分别表示。任一时刻魔板的状态可用方块的颜色序列表示:从魔板的左上角开始,按顺时针方向依次写下各方块的颜色代号,所得到的数字序列即可表示此时魔板的状态。例如,序列(1,2,3,4,5,6,7,8)表示魔板状态为:
1 2 3 4 8 7 6 5
对于魔板,可施加三种不同的操作,具体操作方法如下:
A: 上下两行互换,如上图可变换为状态87654321 B: 每行同时循环右移一格,如上图可变换为41236785 C: 中间4个方块顺时针旋转一格,如上图可变换为17245368
给你魔板的初始状态与目标状态,请给出由初态到目态变换数最少的变换步骤,若有多种变换方案则取字典序最小的那种。
 

 

Input
每组测试数据包括两行,分别代表魔板的初态与目态。
 

 

Output
对每组测试数据输出满足题意的变换步骤。
 

 

Sample Input
12345678 17245368 12345678 82754631
 

 

Sample Output
C AC
  1 #include <iostream>

  2 #include <string>

  3 #include <algorithm>

  4 #include <queue>

  5 using namespace std;

  6 

  7 const int MAXN = 40321;        //由于此题数字1~8,康托展开的所有情况为8!,共40320种 

  8 const int fac[8] = {1,1,2,6,24,120,720,5040};    //康托展开中用到的0~7的阶乘 

  9 string ans[MAXN];                //存储各状态的变化步骤,预处理完成 

 10 

 11 struct node

 12 {

 13     int a[8];

 14     int n;

 15 }u,v;

 16 

 17 void A(node &t)    //A操作 

 18 {

 19     swap(t.a[0],t.a[7]);  

 20     swap(t.a[1],t.a[6]);  

 21    swap(t.a[2],t.a[5]);  

 22    swap(t.a[3],t.a[4]);

 23 }

 24 void B(node &t)    //B操作 



 25 {

 26     swap(t.a[3],t.a[2]);  

 27    swap(t.a[2],t.a[1]);  

 28    swap(t.a[1],t.a[0]);  

 29    swap(t.a[4],t.a[5]);  

 30    swap(t.a[5],t.a[6]);  

 31    swap(t.a[6],t.a[7]);

 32 }

 33 void C(node &t)    //C操作 

 34 {

 35     swap(t.a[1],t.a[6]);  

 36    swap(t.a[6],t.a[5]);  

 37    swap(t.a[5],t.a[2]);

 38 }

 39 

 40 int contor(node &t)        //康托展开

 41 {

 42     int tmp, num = 0;

 43     for(int i=0; i<8; i++)

 44     {

 45         tmp = 0;

 46         for(int j=i+1; j<8; j++)

 47         {

 48             if(t.a[j] < t.a[i])

 49             {

 50                 tmp++;

 51             }

 52         }

 53         num += tmp*fac[7-i];

 54     }

 55     return num;

 56 } 

 57 

 58 void Init(void)

 59 {

 60     void (*ptr[3])(node&);                        //定义函数指针 

 61     ptr[0] = A; ptr[1] = B; ptr[2] = C;        //指向对应函数方便处理 

 62     

 63     int mark[MAXN] = {0};                        //设置标记 

 64     mark[0] = 1;

 65     

 66     for(int i=0; i<8; i++)                        //由初始状态12345678开始 

 67     {

 68         u.a[i] = i+1;

 69     }

 70     u.n = contor(u);

 71     

 72     queue<node>que;

 73     que.push(u);

 74     while(!que.empty())

 75     {

 76         u = que.front();

 77         que.pop();

 78         

 79         for(int i=0; i<3; i++)                //三种变换 

 80         {

 81             v = u;

 82             (*ptr[i])(v);

 83             v.n = contor(v);                    //对副本执行操作并康托展开 

 84             if(mark[v.n] == 0)                //重复 

 85             {

 86                 char ch = 'A' + i;

 87                 ans[v.n] = ans[u.n] + ch;    //记录步骤 

 88                 

 89                 mark[v.n] = 1;                    //标记 

 90                 que.push(v);

 91             }    

 92         }

 93     }

 94 }

 95 

 96 int main()

 97 {

 98     Init();

 99     char a[10],b[10];

100     while(~scanf("%s%s",a,b))

101     {

102         int n[10];

103         for(int i=0; i<8; i++)            //把初态置换成12345678 

104         {

105             n[a[i] - '0'] = i+1;

106         }

107         

108         for(int i=0; i<8; i++)            //把目标状态相对于初态置换 

109         {

110             u.a[i] = n[b[i] - '0'];

111         }

112         

113         cout<<ans[contor(u)]<<endl;    //输出由12345678到目标态的步骤 

114     }

115     return 0;

116 }

 

你可能感兴趣的:(String类)