HDU - 1430 - 魔板( 康托展开 + BFS预处理 )

Posted alphakin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU - 1430 - 魔板( 康托展开 + BFS预处理 )相关的知识,希望对你有一定的参考价值。

魔板

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


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
 
 
----------------------------------------------------------------------------------------------------------------------------
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1430
 
直接BFS + 康托去重会TLE。
双向BFS会遇到反向BFS时处理字典序最小的问题。
 
简单的方法:
  先以 " 12345678 " 为初始状态进行bfs,将并所有情况保存下来,这样可以从" 12345678 "到达任何一种情况。
但是,出状态不一定是" 12345678 ",所以我们可以进行映射。
 
例如:

初状态:4 6 2 8 5 7 3 1
末状态:3 4 8 7 2 5 1 6

可以转换成:

初状态:1 2 3 4 5 6 7 8
末状态:7 1 4 6 3 5 8 2

那么从 " 46285731 " 到 " 34872516 " 的路径 就等于 从 " 1234578 " 到 " 71463582 " 的路径。

而 " 1234578 " 到 " 71463582 " 的路径我们已经记录下来,直接递归打印出结果。

( 答案为: BCBCBCABCABCABBCCBCB )

 

*数据里有初状态和末状态相等的情况,直接输出换行即可。

 

 

附AC代码:

技术分享图片  

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <queue>
  6 #define SIZE 40325
  7 using namespace std;
  8 
  9 const int fac[9] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320};
 10 struct ref{
 11     int parent;
 12     char op;
 13 }ans[SIZE];
 14 
 15 struct node{
 16     char s[10];
 17     int value;
 18     node(){}
 19     node(char * ss, const int v) : value(v){
 20         for(int i=0; i<8; ++i) *(s + i) = *(ss + i);
 21     }
 22 };
 23 
 24 bool vis[SIZE] = {0};
 25 int cantor(char * s){
 26     bool vis[10] = {0};
 27     int rec, ans = 0;
 28     for(int i=0; i<8; ++i){
 29         vis[s[i]] = 1, rec = 0;
 30         for(int j=1; j<s[i]; ++j)
 31             if(!vis[j]) ++rec;
 32         ans += rec * fac[7 - i];
 33     }
 34     return ans + 1;
 35 }
 36 
 37 void swap(char * s, const int posa, const int posb){
 38     char tmp = *(s + posa);
 39     *(s + posa) = *(s + posb);
 40     *(s + posb) = tmp;
 41 }
 42 
 43 void operate(char * s, const char type){
 44     if(type == 0){ for(int i=0; i<4; ++i) swap(s, i, 7-i); }
 45     else if(type == 1) for(int i=0; i<3; ++i) swap(s, i, 3), swap(s, 4, 7 - i);
 46     else { swap(s, 2, 5); swap(s, 1, 2); swap(s, 1, 6); }
 47 }
 48 
 49 void bfs(){
 50     int value, k = 0;
 51     node begin, now, next;
 52     for(int i=0; i<8; ++i) begin.s[i] = i+1;
 53     begin.value = cantor(begin.s);
 54     queue<node> q;
 55     q.push(begin);
 56     int rec = 0;
 57     while(q.size()){
 58         now = q.front(); q.pop();
 59         for(int i=0; i<3; ++i){
 60             next = now;
 61             operate(next.s, i);
 62             if(!vis[ value = cantor(next.s) ]){
 63                 vis[value] = 1;
 64                 q.push(node(next.s, value));
 65                 ans[value].parent = now.value;
 66                 ans[value].op = A + i;
 67             }
 68         }
 69     }
 70 }
 71 
 72 void deal(const int pos){
 73     if(ans[pos].parent == 1){
 74         putchar(ans[pos].op);
 75         return;
 76     }
 77     deal(ans[pos].parent);
 78     putchar(ans[pos].op);
 79 }
 80 
 81 void reflect(char * s, char * e){
 82     char reca[8], recb[8], ss[8];
 83     for(int i=0; i<8; ++i){
 84         reca[s[i]-1] = i, recb[e[i]-1] = i;
 85     }
 86     for(int i=0; i<8; ++i){
 87         *(e + recb[i]) = reca[i] + 1;
 88     }
 89 }
 90 
 91 int main(){
 92     //freopen("in", "r", stdin);
 93     char str[10], ptr[10];
 94     bfs();
 95     while(~scanf("%s%s", str, ptr)){
 96         if(!strcmp(str, ptr)){
 97             putchar(
);
 98             continue;
 99         }
100         for(int i=0; i<8; ++i) str[i] -= 0, ptr[i] -= 0;
101         reflect(str, ptr);
102         deal(cantor(ptr));
103         putchar(
);
104     }
105     return 0;
106 }

 

 

 

 


















以上是关于HDU - 1430 - 魔板( 康托展开 + BFS预处理 )的主要内容,如果未能解决你的问题,请参考以下文章

HDU 1430 魔板

宽搜经典题之三——魔板+康托展开

P2730 魔板 Magic Squares

hdu 1043 Eight(康托展开 + BFS)

hdu1027(逆康托展开)

反向BFS+康托展开Eight HDU - 1043