ACM/ICPC 之 BFS(离线)+康拓展开 (HDU1430-魔板)

  魔板问题,一道经典的康拓展开+BFS问题,为了实现方便,我用string类来表示字符串,此前很少用string类(因为不够高效,而且相对来说我对char数组的相关函数比较熟),所以在这里也发现了很多容易被忽视的问题。



  对于康拓展开不太熟系的可以先参看一篇博客:http://blog.csdn.net/zhongkeli/article/details/6966805

  

  关于sting类,大家要注意,在赋值的时候,其赋值位置不能与首位置间存在未赋值部分

  题目需要转换思路的地方是: 我们需要将起始魔板->目标魔板 转换为 标准魔板->新目标魔板的形式,以便离线(打表)一次就够了。

  具体代码如下:

  1 //魔板问题-BFS(离线)+康拓展开
  2 //Time: 38Ms Memory:6484K
  3 #include<iostream>
  4 #include<string>
  5 #include<queue>
  6 #include<algorithm>
  7 using namespace std;
  8
  9 #define MAX 40321
 10
 11 int fac[8] = { 1,1,2,6,24,120,720,5040 };    //阶乘数组
 12
 13 int v[MAX];        //访问标记
 14 string ans[MAX];    //离线表
 15
 16 struct Board{
 17     int val;    //Hash值
 18     string str;
 19 };
 20
 21 //康拓展开(Hash)
 22 int Contor(string str)
 23 {
 24     int num = 0;    //Hash值
 25     for (int i = 0; i < 8; i++)
 26     {
 27         int tmp = 0;    //在此后的序列中的位置(升序)
 28         for (int j = i + 1; j < 8; j++)
 29             if (str[j] < str[i]) tmp++;
 30         num += tmp*fac[7 - i];
 31     }
 32     return num;
 33 }
 34
 35 //离线打表(BFS)
 36 void Init()
 37 {
 38     queue<Board>Q;
 39     Board t, tmp;
 40     t.str = tmp.str = "12345678";    //初始数组
 41     t.val = Contor(t.str);
 42     v[t.val] = 1;
 43     Q.push(t);
 44     while (!Q.empty()) {
 45         t = Q.front();
 46         Q.pop();
 47
 48         // A:交换行
 49         for (int i = 0; i < 8; i++)
 50             tmp.str[(i + 4) % 8] = t.str[i];
 51
 52         tmp.val = Contor(tmp.str);
 53         if (!v[tmp.val]) {
 54             v[tmp.val] = 1;
 55             ans[tmp.val] = ans[t.val] + ‘A‘;
 56             Q.push(tmp);
 57         }
 58
 59         // B:循环右移
 60         for (int i = 0; i < 4; i++)
 61             tmp.str[(i + 1) % 4] = t.str[i];
 62         for (int i = 4; i < 8; i++)
 63             tmp.str[(i + 1) % 4 + 4] = t.str[i];
 64
 65         tmp.val = Contor(tmp.str);
 66         if (!v[tmp.val]) {
 67             v[tmp.val] = 1;
 68             ans[tmp.val] = ans[t.val] + ‘B‘;
 69             Q.push(tmp);
 70         }
 71
 72         // C:中心顺时旋转
 73         tmp.str = t.str;
 74         tmp.str[1] = t.str[5]; tmp.str[2] = t.str[1];
 75         tmp.str[6] = t.str[2]; tmp.str[5] = t.str[6];
 76
 77         tmp.val = Contor(tmp.str);
 78         if (!v[tmp.val]) {
 79             v[tmp.val] = 1;
 80             ans[tmp.val] = ans[t.val] + ‘C‘;
 81             Q.push(tmp);
 82         }
 83     }
 84 }
 85
 86 int main()
 87 {
 88     Init();    //BFS
 89     string ts, te;
 90     while (cin >> ts >> te)
 91     {
 92         /*转换成顺序魔板*/
 93         swap(ts[5], ts[6]);
 94         swap(ts[4], ts[7]);
 95         swap(te[5], te[6]);
 96         swap(te[4], te[7]);
 97
 98         /*将起始魔板转换为标准魔板,相应目标魔板也进行变更*/
 99         char tmp[9];
100         for (int i = 0; i < 8; i++)
101             tmp[ts[i] - ‘0‘] = i + ‘1‘;
102         for (int i = 0; i < 8; i++)
103             te[i] = tmp[te[i] - ‘0‘];
104
105         cout << ans[Contor(te)] << endl;
106     }
107
108     return 0;
109 }
时间: 2024-12-20 15:20:47

ACM/ICPC 之 BFS(离线)+康拓展开 (HDU1430-魔板)的相关文章

【HDOJ3567】【预处理bfs+映射+康拓展开hash】

http://acm.hdu.edu.cn/showproblem.php?pid=3567 Eight II Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 130000/65536 K (Java/Others)Total Submission(s): 4541    Accepted Submission(s): 990 Problem Description Eight-puzzle, which is also calle

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

魔板 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分别表示.任一时刻魔板的状态可用方块的颜色

hdu1430魔板

Problem Description 在魔方风靡全球之后不久,Rubik先生发明了它的简化版——魔板.魔板由8个同样大小的方块组成,每个方块颜色均不相同,可用数字1-8分别表示.任一时刻魔板的状态可用方块的颜色序列表示:从魔板的左上角开始,按顺时针方向依次写下各方块的颜色代号,所得到的数字序列即可表示此时魔板的状态.例如,序列(1,2,3,4,5,6,7,8)表示魔板状态为: 1 2 3 48 7 6 5 对于魔板,可施加三种不同的操作,具体操作方法如下: A: 上下两行互换,如上图可变换为状

ACM/ICPC 之 BFS+状态压缩(POJ1324(ZOJ1361))

求一条蛇到(1,1)的最短路长,题目不简单,状态较多,需要考虑状态压缩,ZOJ的数据似乎比POj弱一些 POJ1324(ZOJ1361)-Holedox Moving 题意:一条已知初始状态的蛇,求其到(1,1)的最短路长 题解:开始做的时候用BFS暴力做了一次,结果RE了,后来看了其他的题解和discuss才转向状态压缩.也看到有人用A*做出来了. 现在简要介绍一下状态压缩的思路: 由于蛇身最长只有8,可以利用两条相邻蛇身坐标确定其相对方向(四个方向),两位二进制可以表示 这样 一个蛇头坐标+

ACM/ICPC 之 BFS范例(ZOJ2913)

通过一道经典BFS例题阐述BFS思路 ZOJ2913-Bus Pass 题意:找一个center区域,使得center到所有公交线路最短,有等距的center则输出id最小的. 题解:经典的BFS,由公交线路最多只经过10*20个区域,而总区域数可达10^5个,因此应该从公交线路通过队列一层层向外扩展,最后判断一次center的位置即可. 1 //选定一个center使得其到所有公交线路最短 2 //对所有公交线路进行BFS(公交线路比其他区域少得多) 3 //Time:150Ms Memory

HDU-1430 魔板

BFS+预处理. 一组解的话Usaco有题...要是T组解的话就预处理一下. #include <cstdio> #include <iostream> #include <fstream> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <queue> #define rep(i, l,

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分别表示.任一时刻魔板的状态可用方块的颜

hdoj1043 Eight(逆向BFS+打表+康拓展开)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 思路: 由于自己对康拓展开用的太少,看到这个题没想到康拓展开,最开始打算直接转换为数字,但太占内存了,又想到可以将状态存进set,后来查了一下发现原来是考察康拓展开.另外就是需要打表预处理,这样快很多.BFS部分就是已知终点,从终点逆向搜索,并存每个状态的上一个状态以及操作,以便输出. 坑点:输入是多组输入,POJ那道题才是一组输入,卡在这一上午T_T. 有一组输入为12345678x,需要特

HDU 5889 Barricade 【BFS+最小割 网络流】(2016 ACM/ICPC Asia Regional Qingdao Online)

Barricade Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 997    Accepted Submission(s): 306 Problem Description The empire is under attack again. The general of empire is planning to defend his