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(‘\n‘);
 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(‘\n‘);
104     }
105     return 0;
106 }

原文地址:https://www.cnblogs.com/alphakin/p/9382685.html

时间: 2024-11-10 13:57:55

HDU - 1430 - 魔板( 康托展开 + BFS预处理 )的相关文章

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

魔板 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 2921    Accepted Submission(s): 649 Problem Description 在魔方风靡全球之后不久,Rubik先生发明了它的简化版——魔板.魔板由8个同样大小的方块组成,每个方块颜色均不相同,可用数字1-8分别表示.任一时刻魔板的状态可用方块的颜

hdu.1430.魔板(bfs + 康托展开)

魔板 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 2170    Accepted Submission(s): 455 Problem Description 在魔方风靡全球之后不久,Rubik先生发明了它的简化版——魔板.魔板由8个同样大小的方块组成,每个方块颜色均不相同,可用数字1-8分别表示.任一时刻魔板的状态可用方块的颜

BFS [HDU 1430] 魔板

魔板 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 1988    Accepted Submission(s): 407 Problem Description 在魔方风靡全球之后不久,Rubik先生发明了它的简化版——魔板.魔板由8个同样大小的方块组成,每个方块颜色均不相同,可用数字1-8分别表示.任一时刻魔板的状态可用方块的颜色

Hdoj 1430 魔板 【BFS】+【康拓展开】+【预处理】

魔板 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 2139    Accepted Submission(s): 452 Problem Description 在魔方风靡全球之后不久,Rubik先生发明了它的简化版--魔板.魔板由8个同样大小的方块组成,每个方块颜色均不相同,可用数字1-8分别表示.任一时刻魔板的状态可用方块的颜

HDU 3567 Eight II 打表,康托展开,bfs,g++提交可过c++不可过 难度:3

http://acm.hdu.edu.cn/showproblem.php?pid=3567 相比Eight,似乎只是把目标状态由确定的改成不确定的,但是康托展开+曼哈顿为h值的A*和IDA*都不过,而且也不好控制字典序 换个角度想,虽然起始状态有很多,但是到底哪一位是1,哪一位是2不是最重要的,最重要的是和目标状态对应,所以可以把起始状态重新编码为"12345678"这种形式(先不考虑X),然后目标状态也对应过去,当考虑X的时候,我们可以认为起始状态只有9种,分别是'X'在各个位置的

Aizu 0121 Seven Puzzle (康托展开+bfs)

Seven Puzzle Time Limit : 1 sec, Memory Limit : 65536 KB 7パズルは8つの正方形のカードとこれらのカードがぴたりと収まる枠を使って行います.それぞれのカードは互いに区別できるように.0,1,2....7と番号がつけられています.枠には.縦に2個.横に4個のカードを並べることができます. 7パズルを始めるときには.まず枠にすべてのカードを入れます.枠のなかで0のカードだけは.上下左右に隣接するカードと位置を交換することができます.たとえば.枠

POJ 1077 Eight(康托展开+BFS)

Eight Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 30176   Accepted: 13119   Special Judge Description The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've seen it. It is constructed with 15

ACM-康托展开+预处理BFS之魔板——hdu1430

魔板 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 1679    Accepted Submission(s): 354 Problem Description 在魔方风靡全球之后不久,Rubik先生发明了它的简化版--魔板.魔板由8个同样大小的方块组成,每个方块颜色均不相同,可用数字1-8分别表示.任一时刻魔板的状态可用方块的颜

hdu 1430 (BFS 康托展开 或 map )

第一眼看到这题就直接BFS爆搜,第一发爆了内存,傻逼了忘标记了,然后就改,咋标记呢. 然后想到用map函数,就8!个不同的排列,换成字符串用map标记.然后又交一发果断超时,伤心,最恨超时,还不如来个wa算了. 然后卡着了,后来上网上搜了,要用康托展开,康托展开是什么鬼?然后学习了一下,就是个映射,感觉和map差不多. http://blog.csdn.net/zhongkeli/article/details/6966805这个学习一下康托展开. 其实本题的关键不是康托展开,而是置换. 以12