魔板
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 }
时间: 2024-11-03 21:54:52