HDU 1010 Tempter of the Bone【DFS经典题+奇偶剪枝详解】
Tempter of the Bone
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 125945 Accepted Submission(s): 33969
doggie found a bone in an ancient maze, which fascinated him a lot.
However, when he picked it up, the maze began to shake, and the doggie
could feel the ground sinking. He realized that the bone was a trap, and
he tried desperately to get out of this maze.
The maze was a
rectangle with sizes N by M. There was a door in the maze. At the
beginning, the door was closed and it would open at the T-th second for a
short period of time (less than 1 second). Therefore the doggie had to
arrive at the door on exactly the T-th second. In every second, he could
move one block to one of the upper, lower, left and right neighboring
blocks. Once he entered a block, the ground of this block would start to
sink and disappear in the next second. He could not stay at one block
for more than one second, nor could he move into a visited block. Can
the poor doggie survive? Please help him.
input consists of multiple test cases. The first line of each test case
contains three integers N, M, and T (1 < N, M < 7; 0 < T <
50), which denote the sizes of the maze and the time at which the door
will open, respectively. The next N lines give the maze layout, with
each line containing M characters. A character is one of the following:
'X': a block of wall, which the doggie cannot enter;
'S': the start point of the doggie;
'D': the Door; or
'.': an empty block.
The input is terminated with three 0's. This test case is not to be processed.
4 4 5
S.X.
..X.
..XD
....
3 4 5
S.X.
..X.
...D
0 0 0

这道题可以不剪枝操作,也不会T了!
不懂剪枝的看这里:DFS中的奇偶剪枝学习笔记
这里说下不剪枝的技巧:为了避免多余的边界控制,可以从i=1,j=1开始读迷宫,在读之前将迷宫初始化为全部'X',即都为墙。这样在迷宫读取完毕后,周围就会自动出现一圈'X',这样就可以在搜索的时候只判断遇到'X'就return了。
这里贴一下深搜代码,不管剪不剪枝,这一段是可以不用修改的。
inline int DFS(int x,int y,int T)
{
if(mp[x][y]!='.'&&mp[x][y]!='S')//碰到X即为边界返回
return ;
if(T==)//剩一步时即可判断是否为出口,找到返回1
{
if(mp[x-][y]=='D')
return ;
if(mp[x+][y]=='D')
return ;
if(mp[x][y-]=='D')
return ;
if(mp[x][y+]=='D')
return ;
return ;
}
else
{
mp[x][y]='X';//标记走过
if(mp[x-][y]=='.'&&DFS(x-,y,T-))
return ;
if(mp[x+][y]=='.'&&DFS(x+,y,T-))
return ;
if(mp[x][y-]=='.'&&DFS(x,y-,T-))
return ;
if(mp[x][y+]=='.'&&DFS(x,y+,T-))
return ;
mp[x][y]='.';//还原走过
return ;
}
return ;
}
关于奇偶剪枝
首先举个例子,有如下4*4的迷宫,'.'为可走路段,'X'为障碍不可通过
S...
....
....
...D
从S到D的最短距离为两点横坐标差的绝对值+两点纵坐标差的绝对值 = abs(Sx - Dx) + abs(Sy - Dy) = 6,这个应该是显而易见的。
遇到有障碍的时候呢
S.XX
X.XX
...X
...D
你会发现不管你怎么绕路,最后从S到达D的距离都是最短距离+一个偶数,这个是可以证明的
而我们知道:
奇数 + 偶数 = 奇数
偶数 + 偶数 = 偶数
因此不管有多少障碍,不管绕多少路,只要能到达目的地,走过的距离必然是跟最短距离的奇偶性是一致的。
所以如果我们知道从S到D的最短距离为奇数,那么当且仅当给定的步数T为奇数时,才有可能走到。如果给定的T的奇偶性与最短距离的奇偶性不一致,那么我们就可以直接判定这条路线永远不可达了。
这里还有个小技巧,我们可以使用按位与运算来简化奇偶性的判断。我们知道1的二进制是1,而奇数的二进制最后一位一定是1,而偶数的二进制最后一位一定是0。所以如果数字&1的结果为1,那么数字为奇数,反之为偶数。
下面给出奇偶剪枝后的main函数代码:
int main()
{
int sx,sy,dx,dy;
int N,M,T;
while(scanf("%d%d%d",&N,&M,&T)&&N&&M&&T)
{
getchar();
memset(mp,'X',sizeof(mp));//把周围边界全部变成X
for(int i=;i<=N;i++)//从1开始读,留出边界位置
{
for(int j=;j<=M;j++)
{
scanf("%c",&mp[i][j]);
if(mp[i][j]=='S')
{
sx=i;
sy=j;
}
else if(mp[i][j]=='D')
{
dx=i;
dy=j;
}
}
getchar();
}
if((abs(sx-dx)+abs(sy-dy)-T)&)//奇偶剪枝,对1用按位与运算求奇偶
printf("NO\n");
else if(DFS(sx,sy,T)==)
printf("YES\n");
else printf("NO\n");
}
return ;
}
所以完整的AC代码如下:
#include <bits/stdc++.h>
using namespace std;
char mp[][];
inline int DFS(int x,int y,int T)
{
if(mp[x][y]!='.'&&mp[x][y]!='S')//碰到X即为边界返回
return ;
if(T==)//剩一步时即可判断是否为出口,找到返回1
{
if(mp[x-][y]=='D')
return ;
if(mp[x+][y]=='D')
return ;
if(mp[x][y-]=='D')
return ;
if(mp[x][y+]=='D')
return ;
return ;
}
else
{
mp[x][y]='X';//标记走过
if(mp[x-][y]=='.'&&DFS(x-,y,T-))
return ;
if(mp[x+][y]=='.'&&DFS(x+,y,T-))
return ;
if(mp[x][y-]=='.'&&DFS(x,y-,T-))
return ;
if(mp[x][y+]=='.'&&DFS(x,y+,T-))
return ;
mp[x][y]='.';//还原走过
return ;
}
return ;
}
int main()
{
int sx,sy,dx,dy;
int N,M,T;
while(scanf("%d%d%d",&N,&M,&T)&&N&&M&&T)
{
getchar();
memset(mp,'X',sizeof(mp));//把周围边界全部变成X
for(int i=;i<=N;i++)//从1开始读,留出边界位置
{
for(int j=;j<=M;j++)
{
scanf("%c",&mp[i][j]);
if(mp[i][j]=='S')
{
sx=i;
sy=j;
}
else if(mp[i][j]=='D')
{
dx=i;
dy=j;
}
}
getchar();
}
if((abs(sx-dx)+abs(sy-dy)-T)&)//奇偶剪枝,对1用按位与运算求奇偶
printf("NO\n");
else if(DFS(sx,sy,T)==)
printf("YES\n");
else printf("NO\n");
}
return ;
}
HDU 1010 Tempter of the Bone【DFS经典题+奇偶剪枝详解】的更多相关文章
- hdu 1010 Tempter of the Bone(深搜+奇偶剪枝)
Tempter of the Bone Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Othe ...
- HDU 1010 Tempter of the Bone --- DFS
HDU 1010 题目大意:给定你起点S,和终点D,X为墙不可走,问你是否能在 T 时刻恰好到达终点D. 参考: 奇偶剪枝 奇偶剪枝简单解释: 在一个只能往X.Y方向走的方格上,从起点到终点的最短步数 ...
- HDU 1010 Tempter of the Bone(DFS+奇偶剪枝)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1010 题目大意: 输入 n m t,生成 n*m 矩阵,矩阵元素由 ‘.’ 'S' 'D' 'X' 四 ...
- hdu.1010.Tempter of the Bone(dfs+奇偶剪枝)
Tempter of the Bone Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Othe ...
- HDU 1010 Tempter of the Bone (DFS+可行性奇偶剪枝)
<题目链接> 题目大意:一个迷宫,给定一个起点和终点,以及一些障碍物,所有的点走过一次后就不能再走(该点会下陷).现在问你,是否能从起点在时间恰好为t的时候走到终点. 解题分析:本题恰好要 ...
- hdu - 1010 Tempter of the Bone (dfs+奇偶性剪枝) && hdu-1015 Safecracker(简单搜索)
http://acm.hdu.edu.cn/showproblem.php?pid=1010 这题就是问能不能在t时刻走到门口,不能用bfs的原因大概是可能不一定是最短路路径吧. 但是这题要过除了细心 ...
- (step4.3.1) hdu 1010(Tempter of the Bone——DFS)
题目大意:输入三个整数N,M,T.在接下来的N行.M列会有一系列的字符.其中S表示起点,D表示终点. .表示路 . X表示墙...问狗能有在T秒时到达D.如果能输出YES, 否则输出NO 解题思路:D ...
- HDU 1010 Tempter of the Bone DFS(奇偶剪枝优化)
需要剪枝否则会超时,然后就是基本的深搜了 #include<cstdio> #include<stdio.h> #include<cstdlib> #include ...
- HDOJ.1010 Tempter of the Bone (DFS)
Tempter of the Bone [从零开始DFS(1)] 从零开始DFS HDOJ.1342 Lotto [从零开始DFS(0)] - DFS思想与框架/双重DFS HDOJ.1010 Tem ...
随机推荐
- OC学习8——异常处理
1.和Java一样,OC也有自己的一套异常处理机制,不同的是,OC中的异常处理机制并不是作为常规的编程实践,通常只是作为一种程序调试.排错机制. 2.与Java中类似,OC中也是采用@try...@c ...
- visual studio 2012打开提示 未能将网站×××配置为使用 ASP.NET 4.5 和 尚未在Web服务器上注册,您需要手动将Web服务器配置为使用ASP.NET 4.5
未能将网站×××配置为使用 ASP.NET 4.5.为了使此网站正确运行,您必须将它手动配置为使用ASP.NET 4.5. ASP.NET 4.5尚未在Web服务器上注册,您需要手动将Web服务器配置 ...
- class_copyIvarList方法获取实例变量问题引发的思考
在runtime.h中,你可以通过其中的一个方法来获取实例变量,那就是class_copyIvarList方法,具体的实现如下: - (NSArray *)ivarArray:(Class)cls { ...
- apache泛域名解析
<VirtualHost *:80> DocumentRoot "E:\work\phpStudy\WWW\ncpx\web" ServerName ncp ...
- 怎么选择公司???MVC加jquery-easyui 后端工程师
代码管理 Git 架构 MVC 这样的项目扩展性强,维护性强!!! 别很老的asp.net 不用框架!!!
- 解决openssh漏洞,升级openssh版本
关于解决漏洞的问题我就不详说了,主要就是升级版本.这里我们就直接简单记录下步骤: 1.升级 使用root用户登录系统进入到/home/guankong ,上传openssh-6.6p1.tar.gz到 ...
- java数组去重
java数组去重 1.创建新数组,用于保存比较结果 2.设定随机数组最大最小值 3.开始去重 4.计算去重所需时间 package org.zheng.collection; import java. ...
- Sticky Footer 绝对底部的两种套路
最近面了好几个前端,工作经验有高有低,居然都不知道绝对底部是什么,也没有人能说出一种实现方式,让我不禁感慨前端领域的良莠不齐 绝对底部,或者说 Sticky Footer,是一种古老且经典的页面效果: ...
- Head First设计模式之代理模式
一.定义 定义:为其他对象提供一种代理以控制对这个对象的访问 在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口. 二.结构 代理模式一般会有三个角色: 抽象角色(Subject):指代 ...
- MicroPython-GPRS教程之TPYBoardv702GPRS功能测试
一.什么是TPYBoardV702 TPYBoardV702是目前市面上唯一支持通信通信功能的MicroPython开发板:支持Python3.0及以上版本直接运行.支持GPS+北斗双模通信.GPRS ...