标签:
原题地址:http://acm.hdu.edu.cn/showproblem.php?pid=1430
魔板
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2311 Accepted Submission(s): 485
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
思路:
初态a和末态b经过相同的一系列操作,使初态a变成12345678,同时得到新的末态c,然后只需要求12345678到末态c的变换步骤即为初态a到末态b的变换步骤。所以,只要把12345678的所有可达状态遍历一次并记录下变换步骤即可。
1 #include <cstdio> 2 #include <string.h> 3 #include <stack> 4 using namespace std; 5 const int MAX = 40500, fact[] = {1, 1, 2, 6, 24, 120, 720, 5040}, Move[3][8] = {{7, 6, 5, 4, 3, 2, 1, 0}, {3, 0, 1, 2, 5, 6, 7, 4}, {0, 6, 1, 3, 4, 2, 5, 7}}; 6 bool vis[MAX] = {0}; 7 int LOG[MAX][8] = {1, 2, 3, 4, 5, 6, 7, 8}; 8 struct node 9 { 10 char MOVE; 11 int father; 12 }path[MAX]; 13 bool TryToInsert(int Front, int Rear, int MOVE) 14 { 15 int Fcode = 0, Rcode = 0, i, j, cnt; 16 for(i=0; i<7; ++i) 17 { 18 cnt = 0; 19 for(j=i+1; j<8; ++j) 20 if(LOG[Rear][i] > LOG[Rear][j]) 21 ++cnt; 22 Rcode += cnt * fact[7-i]; 23 } 24 if(vis[Rcode]) 25 return false; 26 else 27 { 28 for(i=0; i<7; ++i) 29 { 30 cnt = 0; 31 for(j=i+1; j<8; ++j) 32 if(LOG[Front][i] > LOG[Front][j]) 33 ++cnt; 34 Fcode += cnt * fact[7-i]; 35 } 36 path[Rcode].father = Fcode; 37 path[Rcode].MOVE = ‘A‘ + MOVE; 38 return vis[Rcode] = true; 39 } 40 } 41 void BFS(void) 42 { 43 vis[0] = true; 44 int Front = 0, Rear = 1, i, j; 45 do 46 { 47 for(i=0; i<3; ++i) 48 { 49 for(j=0; j<8; ++j) 50 LOG[Rear][j] = LOG[Front][ Move[i][j] ]; 51 if(TryToInsert(Front, Rear, i)) 52 ++Rear; 53 } 54 ++Front; 55 } while (Front < Rear); 56 } 57 int main(void) 58 { 59 BFS(); 60 stack<char> s; 61 int Start[8], End[8], Aim[8], AimCode, i, j, cnt; 62 char StartStr[10], EndStr[10]; 63 while(~scanf("%s%s", StartStr, EndStr)) 64 { 65 for(i=0; i<8; ++i) 66 { 67 Start[i] = StartStr[i] - ‘0‘; 68 End[i] = EndStr[i] - ‘0‘; 69 } 70 for(i=0; i<8; ++i) 71 { 72 for(j=0; End[i] != Start[j]; ++j); 73 Aim[i] = j+1; 74 } 75 AimCode = 0; 76 for(i=0; i<7; ++i) 77 { 78 cnt = 0; 79 for(j=i+1; j<8; ++j) 80 if(Aim[i] > Aim[j]) 81 ++cnt; 82 AimCode += cnt * fact[7-i]; 83 } 84 while(AimCode) 85 { 86 s.push(path[AimCode].MOVE); 87 AimCode = path[AimCode].father; 88 } 89 while(!s.empty()) 90 { 91 printf("%c", s.top()); 92 s.pop(); 93 } 94 printf("\n"); 95 } 96 }
标签:
原文地址:http://www.cnblogs.com/gwtan/p/4779350.html