
ACM-ICPC寒假算法训练1:搜索 HDOJ P1010 : Tempter of the Bone 奇偶剪枝分析
发布日期:2021-05-07 02:18:39
浏览次数:17
分类:精选文章
本文共 2206 字,大约阅读时间需要 7 分钟。
今天学习奇偶剪枝技巧(DFS)
题目大意与思考:
这题说在这个地图中,给你个时间 t ,出口的大门会每隔 t 秒钟打开一次,问你能不能从这个地图中离开。而且这个地图中的位置经过了一次就不能经过第二次。
算法分析:
单纯的算法来看,这题是一道典型的搜索问题。那能不能是 BFS呢?肯定不行,因为 BFS虽然是最短的时间到达出口,但是最短的时间并不一定能赶上大门打开的时间。然而就需要试探、回溯、那么肯定就是用 DFS了!
如何设计 DFS算法呢?一开始的时候大门是关闭的,每 t 秒钟会打开一次,也就是说,如果我到达终点并且大门是打开的,我就成功逃脱了!这时候结束递归。但是还有不成功的情况呢?什么情况是不成功的呢?奇偶剪枝:
假设起点:start(sx, sy),终点:end(ex, ey);
我们容易证明,在没有障碍的情况下,曼哈顿距离:abs(sx - ex) + abs(sy - ey)是从起点到终点的最短距离! 如果我们想要在 t 步的时候走到终点,我们就需要:t - (abs(sx - ex) + abs(sy - ey)) 是一个偶数!
这个结论是怎么来的呢?

证明奇偶剪枝:
从上面的图我们可以理解,分情况讨论:
第一种情况:
同映射(0 -> 0 or 1 -> 1)
需要偶数步,也就是可达步数必须是偶数(step & 1 = 0) 同时,曼哈顿距离也是偶数第二种情况:
异映射(1 -> 0 or 0 -> 1)
需要奇数步,可达步数必须是奇数(step & 1 = 1) 同时曼哈顿距离是奇数综上所述:
如果我预期在 step 的步数(时间)内,到达终点(ex, ey)
那么我当前的位置(x, y)与终点的曼哈顿距离,必须与期望步数同奇偶性! 所以:结论如下step + (abs(x - ex) + abs(y - ey)) & 1 == 0
其中:step = Time - StepNow(预期总步数减去已经走掉了的步数)
Solving code:
#define _CRT_SECURE_NO_WARNINGS#include#include #include const int maxn = 10;int n, m, t, vis[maxn][maxn], bx, by, ex, ey, ans, wall;int dir[4][2] = { {0, 1},{0, -1},{1, 0},{-1, 0} };char mp[maxn][maxn];void dfs(int x, int y, int step) { if (x == ex && y == ey && 0 == step % t) { ans = 1; return; } int temp = abs(step - t) + (abs(x - ex) + abs(y - ey)); if (temp & 1) { ans = 0; return; } for (int i = 0; i < 4; i++) { int dx = x + dir[i][0], dy = y + dir[i][1]; if (dx >= 0 && dx < n && dy >= 0 && dy < m && 'X' != mp[dx][dy]) { if (!vis[dx][dy]) { vis[dx][dy] = 1; step++; dfs(dx, dy, step); step--; vis[dx][dy] = 0; } } }}int main() { while (~scanf("%d %d %d", &n, &m, &t) && (n || m || t)) { getchar(); ans = 0, wall = 0; for (int i = 0; i < n; i++) { scanf("%s", mp[i]); for (int j = 0; j < m; j++) { if ('S' == mp[i][j]) bx = i, by = j; if ('D' == mp[i][j]) ex = i, ey = j; if ('X' == mp[i][j]) wall++; vis[i][j] = 0; } getchar(); } if (n * m - wall <= t) { printf("NO\n"); continue; } vis[bx][by] = 1; dfs(bx, by, 0); if (ans) printf("YES\n"); else printf("NO\n"); } return 0;}
最后一点剪枝:
统计墙壁的数目,如果剩余的可走的位置小于等于需要走的步数,就必然走不通,小于可以理解,那为何是小于等于呢??如果可走的位置恰恰等于需要走的步数,由于一开始狗狗所在的位置就不能再走,所以相当于可走的空间只有:
n * m - wall - 1 < t <=> n * m - wall <= t发表评论
最新留言
能坚持,总会有不一样的收获!
[***.219.124.196]2025年03月20日 06时39分31秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
自定义Hive Sql Job分析工具
2021-05-08
【MySQL】(九)触发器
2021-05-08
关于Altium Designer 09导出BOM表不能正确分类问题
2021-05-08
Oracle 11G环境配置
2021-05-08
【Python】(十二)IO 文件处理
2021-05-08
【Oozie】(三)Oozie 使用实战教学,带你快速上手!
2021-05-08
师兄面试遇到这条 SQL 数据分析题,差点含泪而归!
2021-05-08
C语言的数值溢出问题(上)
2021-05-08
BottomNavigationView控件item多于3个时文字不显示
2021-05-08
函数指针的典型应用-计算函数的定积分(矩形法思想)
2021-05-08
8051单片机(STC89C52)以定时器中断模式实现两倒计时器异步计时
2021-05-08
用 wxPython 打印你的 App
2021-05-08
vue项目通过vue.config.js配置文件进行proxy反向代理跨域
2021-05-08
Linux下安装MySql过程
2021-05-08
android:使用audiotrack 类播放wav文件
2021-05-08
vue通过better-scroll 封装自定义的下拉刷新组件
2021-05-08
android解决:使用多线程和Handler同步更新UI
2021-05-08
Element UI 中动态路由的分析及实现
2021-05-08
使用springMVC配置视图管理器后找不到指定的页面
2021-05-08
杭电 2007 平方和与立方和(输入数据的大小顺序并不能默认)
2021-05-08