[迭代加深 A *] Palamaze (皇宫VS迷宫)
2012-10-12 16:46
211 查看
皇宫VS迷宫(palamaze) 问题描述 FISH社会还是封建制度,皇帝是最高统治者,皇宫作为皇帝吃喝完乐的场所,警卫森严,一般人一旦进入,就很难活着出来。与其说它是个皇宫,还不如说他是个迷宫。 这个巨大的迷宫花费了无数蠢得要死的FISH的辛勤劳动建成,因此结构极其复杂,而且到处机关重重。 首先它是由N*M个格子构成的矩形区域。有的格子是石头,无法穿越(黄色部分);而有的格子是水(白色部分),水中如果没有管道(彩色长条),则FISH可以在里面自由泳;但在一些水中可能存在连接上下或左右两个格子的管道,FISH不能逗留在有管道的格子里,但是可以从一个纵向的管道的下面那个格子、穿过这个管道、游到管道上面的那个格子,前提是这两个格子都不是石头。同样也可以反过来游,横向的管道也是类似的。任何管道所在格子都不相邻。 某些格子中还存放有一些管道的钥匙,一旦得到某片钥匙时,就可以改变与之对应的管道(图中颜色相等)的方向,前提是先游到管道所在格的相邻格子(上下左右共边的格子为相邻格)。一旦FISH游到一个格子,FISH就会用最快速度搜寻一遍这个格子和上下左右相邻的格子,然后把在格中找到的钥匙当作宝贝一样的吞进肚子里(要用的时候再吐出来)。一个格子中可能没有钥匙,但不可能有多片钥匙。迷宫中仅存在一个出口,FISH到那一格就可以重见天日。 如果有钥匙,旋转管道是十分快捷的,四肢发达的FISH(虽然似乎没有四肢)将不费吹灰之力迅速的改变某个管道的方向,前提是获得了那个管道的对应钥匙。每一个时刻FISH可以从一个格子游到上下左右相邻的另一个格子(前提:不能游到石头里,也不能有管道),或者穿过某个相邻格的管道达到一个距离为2的格子(上上、下下、左左、右右4个格子),当然也不能为石头或管道。 为了防止其他进入迷宫的人探索出迷宫的出路,迷宫有一种高级自动关闭系统,当它检测到一条FISH进入到迷宫中时,迷宫会自动从0开始计时。当计到10000后,迷宫会自动关闭,里面的一切生灵(包括FISH算了)都无逃逸的可能了——所以一旦进入迷宫,必须在最少的步数内逃离!否则,嘿嘿~ 死得你一瞧起。 虽然很多人对FISH的死将无动于衷,更有甚者将会幸灾乐祸,但是作为一个正直、智慧、无私、伟大、光明、圣洁的人,你觉得应该为FISH做点什么,比如告诉他:至少需要多少时刻才能逃离迷宫(FISH不要高兴的太早,反正告诉了步数你也不一定能够逃出来的)。 输入文件(palamaze.in) 第一行两个数n,m。(n,m<=20)表示n行m列 接下来。N行m列的矩阵。 ‘*’表示障碍 ‘+’表示正常的路 ‘#’表示起点 ‘$’表示终点 数字表示钥匙,大写字母表示桥横放,小写字母表示桥竖放 不超过9对字母 其中1对应a,A依次类推 输出文件(palamaze.out) 一行,表示最小步数。如果不能逃出,输出10001。 样例输入 4 4 **** *#+* *+$* **** 样例输出 2
初次看到这道题不晓得状态是什么,以为如果要广搜的话,要把整个地图都压进去,压位也会挂空间,于是就写了迭代加深 A *,然后加了一点小优化卡深度,骗了 60 分,感觉还可以的样子。
后来听 ccl 说,只要一个坐标和钥匙集合就可以描述一个状态了。想想也对:之所以觉得要压整个图,就是觉得管道的翻转需要被记。但是如果有了钥匙,随他管道是什么样子都可以过;如果没有钥匙,管道顺着方向可以过,逆着就不可以了。也就是说,如果没有钥匙,管道不变;有钥匙就可以无视管道。所以这道题的状态其实是三维的:x, y, z, 分别表示坐标和钥匙集合。
然后因为不想写广搜了,所以写了 ID,顺便加了个 A *,但感觉优化力度不太大,可能是因为图上很多障碍物而没有什么空旷处之类吧。
再者,为了避免转圈圈而导致解非最优,每次松弛一下一个点的最短路径即可。为了避免清空数组,我写了时间戳。
Code :
#include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #define swap(a, b, t) ({t _ = (a); (a) = (b); (b) = _;}) #define max(a, b) ({int _ = (a), __ = (b); _ > __ ? _ : __;}) #define min(a, b) ({int _ = (a), __ = (b); _ < __ ? _ : __;}) const int dx[5] = {0, 0, - 1, 0, 1}; const int dy[5] = {0, - 1, 0, 1, 0}; int n, m, x1, y1, x2, y2, lim; char a[22][22]; bool b[22][22]; int c[22][22], d[22][22], e[22][22]; int f[22][22][1005], g[22][22][1005]; int getdist(int x, int y) { if ((x -= x2) < 0) x = - x; if ((y -= y2) < 0) y = - y; return x + y + 1 >> 1; } bool okay(int dep, int x, int y, int z) { if (g[x][y][z] < lim || g[x][y][z] == lim && dep < f[x][y][z]) return f[x][y][z] = dep, g[x][y][z] = lim, 1; else return 0; } void dfs(int dep, int x, int y, int z) { if (a[x][y] == '$') printf("%d\n", lim), exit(0); if (b[x][y] || dep + getdist(x, y) > lim) return; for (int i = 0; i <= 4; ++ i) if (~ c[x + dx[i]][y + dy[i]]) z |= 1 << c[x + dx[i]][y + dy[i]]; for (int i = 1; i <= 4; ++ i) { int xx = x + dx[i], yy = y + dy[i]; if (~ d[xx][yy] && (((z >> d[xx][yy]) & 1) || ((i == 1 || i == 3) ^ (e[xx][yy])))) if (okay(dep, xx + dx[i], yy + dy[i], z)) dfs(dep + 1, xx + dx[i], yy + dy[i], z); if (! b[xx][yy]) if (okay(dep, xx, yy, z)) dfs(dep + 1, xx, yy, z); } } void work() { for (lim = 1; lim <= 10000; ++ lim) dfs(0, x1, y1, 0); puts("10001"); } void init() { scanf("%d%d\n", & n, & m); for (int i = 1; i <= n; ++ i) gets(a[i] + 1); for (int i = 0; i <= n + 1; ++ i) a[i][0] = a[i][m + 1] = '*', b[i][0] = b[i][m + 1] = 1; for (int j = 0; j <= m + 1; ++ j) a[0][j] = a[n + 1][j] = '*', b[0][j] = b[n + 1][j] = 1; memset(c, 0xFF, sizeof c), memset(d, 0xFF, sizeof d); for (int i = 1; i <= n; ++ i) for (int j = 1; j <= m; ++ j) { if (a[i][j] == '#') x1 = i, y1 = j; if (a[i][j] == '$') x2 = i, y2 = j; if (a[i][j] == '*' || 'A' <= a[i][j] && a[i][j] <= 'z') b[i][j] = 1; if ('1' <= a[i][j] && a[i][j] <= '9') c[i][j] = a[i][j] - '1'; if ('A' <= a[i][j] && a[i][j] <= 'Z') d[i][j] = a[i][j] - 'A', e[i][j] = 0; if ('a' <= a[i][j] && a[i][j] <= 'z') d[i][j] = a[i][j] - 'a', e[i][j] = 1; } } int main() { freopen("palamaze.in", "r", stdin); freopen("palamaze.out", "w", stdout); init(); work(); return 0; }
相关文章推荐
- 【CodeVS1004】四子连棋-迭代加深搜索入门
- [codevs1288]埃及分数 迭代加深搜索
- 【日常学习】【迭代加深搜索+哈希】codevs1004 四子连棋题解
- codevs 1288 埃及分数 迭代加深搜索
- codevs1288埃及分数-迭代加深搜索
- 迭代加深与A*启发式的结合——IDA*(迷宫问题)
- code[vs] 1004 四子连棋(迭代加深搜索)
- CJOJ 2244 皇宫VS迷宫
- codevs 2541 幂运算(迭代加深搜索)
- [CODEVS1288]埃及分数(迭代加深搜索)
- 【日常学习】【迭代加深搜索】codevs1049 棋盘染色题解
- 迭代加深搜索[codevs1004 四子连棋]
- [codevs1288]埃及分数(迭代加深搜索)
- 【BFS】皇宫VS迷宫
- codevs 2541 幂运算(迭代加深搜索)
- CodeVS 1288 迭代加深 解题报告
- [迭代加深搜索] Codevs1288 埃及分数问题
- hdu 2485 Destroying the bus stations 迭代加深搜索
- usaco4.12Fence Rails(迭代加深)
- UVA 1374 迭代加深搜索