码迷,mamicode.com
首页 > 其他好文 > 详细

hdu1430魔板(广搜+康托展开+string应用)

时间:2015-11-08 22:21:21      阅读:319      评论:0      收藏:0      [点我收藏+]

标签:

魔板

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2420    Accepted Submission(s): 511


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
 

 

Author
LL
 

 

Source
 

 

Recommend
linle   |   We have carefully selected several similar problems for you:  1429 1426 1427 1401 1043 
  1 #include<iostream>
  2 #include <cstdio>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include <string>//定义string类型的变量是需要头文件
  6 #include<queue>
  7 using namespace std;
  8 char a[10],b[10];
  9 int visit[50000];
 10 int f[10]= {1,1,2,6,24,120,720,5040}; //1-7的阶层,康托展开需要用到
 11 string str[500000];  //存放康托展开的变换过程
 12 struct node
 13 {
 14     char num[8];//记录当前字符串
 15     int ct;//记录康托值
 16 };
 17 node node1,node2;
 18 
 19 void way(int k)//将12345678经过0,1,2三种变换方式
 20 {
 21     if(k==0)//87654321
 22     {
 23         for(int i=0; i<4; i++)
 24         {
 25             node2.num[i]=node1.num[7-i];
 26             node2.num[i+4]=node1.num[3-i];
 27         }
 28     }
 29     else if(k==1)//41236785
 30     {
 31         node2.num[0]=node1.num[3];
 32         node2.num[7]=node1.num[4];
 33         for(int i=1; i<4; i++)
 34         {
 35             node2.num[i]=node1.num[i-1];
 36             node2.num[i+3]=node1.num[i+4];
 37         }
 38     }
 39     else//17245368
 40     {
 41         node2.num[0]=node1.num[0];
 42         node2.num[1]=node1.num[6];
 43         node2.num[2]=node1.num[1];
 44         node2.num[3]=node1.num[3];
 45         node2.num[4]=node1.num[4];
 46         node2.num[5]=node1.num[2];
 47         node2.num[6]=node1.num[5];
 48         node2.num[7]=node1.num[7];
 49     }
 50 }
 51 //康托展开的公式是 X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0! 其中,ai为当前未出现的元素中是排在第几个(从0开始)
 52 int kangtuo(char ch[]) //计算康托展开的数字,方法详见“康托展开”博客
 53 {
 54     int s=0,w;
 55     for(int i=0; i<8; i++)
 56     {
 57         w=0;
 58         for(int j=i+1; j<8; j++)
 59         {
 60             if(ch[j]<ch[i])
 61                 w++;
 62         }
 63         s+=w*f[7-i];
 64     }
 65     return s;
 66 }
 67 void bfs()
 68 {
 69 
 70     int n;
 71     char c;
 72     queue<node> q;
 73     while(!q.empty())
 74         q.pop();
 75 
 76     strcpy(node1.num,"12345678");//起始状态虽然不是12345678,但是可以把它看做12345678
 77     node1.ct=0;//初始康托值为0
 78     memset(visit,0,sizeof(visit));
 79     visit[0]=1;
 80     str[0]="";
 81     q.push(node1);
 82     while(!q.empty())
 83     {
 84         node1=q.front();
 85         q.pop();
 86         for(int i=0; i<3; i++)
 87         {
 88             way(i);//变换后的字符记录在node2.num上
 89             n=kangtuo(node2.num);//此时的康托值
 90             if(!visit[n])//通过判断康托值是否出现以此记录这个串是否出现
 91             {
 92                 visit[n]=1;//这个康托值标记为已出现
 93                 c=A+i; //变换的方案
 94                 node2.ct=n;//保存当前串的康托值
 95                 str[n]=str[node1.ct]+c; //记录变换过程
 96                 q.push(node2);
 97             }
 98         }
 99     }
100 }
101 int main()
102 {
103     char ch[10];
104     int nums;
105     bfs();//预处理打表
106     while(~scanf("%s%s",a,b))
107     {
108         for(int i=0; i<8; i++)
109         {
110             ch[a[i]-0]=i+1+0;//建立对应关系,记录起始数据每个数的位置,必须借用ch[]保存
111         }
112         for(int j=0; j<8; j++)
113         {
114             b[j]=ch[b[j]-0];//置换,利用位置变换形成新的字符串
115         }
116         // for(int k=0;k<8;k++)//测试
117         // printf("%d",b[k]);
118         nums=kangtuo(b);//计算康托展开的数
119         //  printf("%d\n",nums);//测试
120         cout<<str[nums]<<endl; //根据康托展开记录的数字查找
121     }
122 }

 

 

hdu1430魔板(广搜+康托展开+string应用)

标签:

原文地址:http://www.cnblogs.com/dshn/p/4948431.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!