[迭代加深 A *] Palamaze (皇宫VS迷宫)
来源:互联网 发布:众途软件 编辑:程序博客网 时间:2024/04/29 04:34
皇宫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;}
- [迭代加深 A *] Palamaze (皇宫VS迷宫)
- 【BFS】皇宫VS迷宫
- CJOJ 2244 皇宫VS迷宫
- code vs 1288 埃及分数 (迭代加深搜)
- code[vs] 1004 四子连棋(迭代加深搜索)
- IDA*(迭代加深的A*算法) 八数码
- [UVa 11212] Editing a Book (迭代加深搜索)
- uva 11212 - Editing a Book(迭代加深搜索 IDA*) 迭代加深搜索
- [jzoj]1262. 为奶牛熄灯(迭代加深搜索+一堆优化vs记忆化vs状压DP)
- 埃及分数(迭代加深搜索)
- 埃及分数(迭代加深搜索)
- 埃及分数(迭代加深搜)
- 埃及分数(迭代加深搜索)
- 迭代加深搜索(埃及分数)
- uva12558 (迭代加深搜索)
- 棋盘染色(迭代加深搜索)
- 剪格子(迭代加深搜索)
- 埃及分数(迭代加深搜索)
- PHP相关系列 - PHP CLI
- 簇 扇区
- COM的常用函数
- 内存对齐的规则以及作用
- 框架Iframe指定网页位置嵌套代码
- [迭代加深 A *] Palamaze (皇宫VS迷宫)
- 优秀有价值的博客收藏列表
- ScaleGestureDetector使用注意事项
- 关于UTF8,UTF16,UTF32,UTF16-LE,UTF16-BE
- ORACLE 11g告警日志存储路径
- 性能指标
- Flex Blazeds推送机制
- kshell 如何查看历史命令 以及执行历史命令 hsitory r[number] r[chars]的语法以及用法
- Oracle数据导入导出