您的位置:首页 > 其它

hdu Tempter of the Bone(DFS)

2016-11-30 13:34 316 查看
Tempter of the Bone

博客转载自:http://blog.csdn.net/libin56842/article/details/8962512
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1010
题目大意:给定你起点S,和终点D,问你是否能在 T 时刻恰好到达终点D.
但在解答时不能直接用dfs,会出现超时情况,其中便涉及到剪枝问题

奇偶性剪枝



再看这段代码:

ans=t-cnt-s1-s2;
其中t-cnt就是还可以走的即剩余的时间或者是步数,s1+s2为剩余需要走的步数

如果走偶数步要求的时间是奇数,或者是走奇数步要求的时间是偶数,很明显都不可行。

而可以轻易得出 奇数-偶数=奇数,反之亦然。而奇数-奇数=偶数,偶数-偶数=偶数,因此ans必须为偶数。(奇偶数剪枝比较容易理解的解释:点击打开链接

----------------理解了这个就很容易了。

代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int n,m,t;
char map[10][10];
char to[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
int flag,di,dj;
void dfs(int si,int sj,int cnt)
{
if(si>n||sj>m||si<=0||sj<=0)//越界
return ;
if(cnt==t&&si==di&&sj==dj)//到达终点
flag=1;
if(flag)
return ;
int s1=abs(di-si);
int s2=abs(dj-sj);
int ans=t-cnt-s1-s2;
if(ans<0||ans&1)//看剩下的时间能能否到达终点,ans&1则是判断其是否偶数,根据奇偶性剪枝可得ans必须是偶数
return ;
for(int i=0;i<4;i++)
{
if(map[si+to[i][0]][sj+to[i][1]]!='X')
{
map[si+to[i][0]][sj+to[i][1]]='X';//走过的地方变为墙
dfs(si+to[i][0],sj+to[i][1],cnt+1);
map[si+to[i][0]][sj+to[i][1]]='.';//迷宫还原,以便下次搜索
}
}
return ;
}
int main()
{
while(~scanf("%d%d%d%*c",&n,&m,&t),n||m||t)
{
memset(map,'\0',sizeof(map));
int si,sj,i,j,wall=0;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
scanf("%c",&map[i][j]);
if(map[i][j]=='S')

4000
si=i,sj=j;
else if(map[i][j]=='D')
di=i,dj=j;
else if(map[i][j]=='X')
wall++;
}
getchar();
}
if(n*m-wall<=t)//t是代表要走的步数,步数加墙数必须小于总格子数的,因为所有格子中还包括了S和D,这是剪枝  
printf("NO\n");
else
{
flag=0;
map[si][sj]='X';;//出发点是不可能再走的了,变为墙
dfs(si,sj,0);
if(flag)
printf("YES\n");
else
printf("NO\n");
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: