hdu 1010 小狗吃骨头(DFS+剪枝)

Tempter of the Bone

 hdu 1010 小狗啃骨头

The 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

The 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. 

Output

For each test case, print in one line "YES" if the doggie can survive, or "NO" otherwise. 

Sample Input

4 4 5
S.X.
..X.
..XD
....
3 4 5
S.X.
..X.
...D
0 0 0

Sample Output

NO
YES

题意概括:

大概就是小狗从S点走到D点吃骨头,而且D点只会在t时刻出现骨头,问小狗是否能够吃到骨头

解题思路:

这题是一道基本的深搜问题,但是时间会超限,然后就需要剪枝处理,这里主要说一下剪枝的问题,首先判断非墙壁的位置的数目是否大于给的时间大小,如果小于的话直接就可以不用考虑了,因为时间是固定的不能走重复的路。然后就是奇偶剪枝的考虑因为从一个点到另外一个点的步数的奇偶性永远都是固定的,无论怎么绕行,所以对于任意路线的一个任意位置到目的地的奇偶性与已走的步数的奇偶性相加必须和最短路径的奇偶性是一致的。就是当前位置到终点的步数v=abs(x-p)+abs(y-q);的奇偶性与限制所剩的步数t-step的奇偶性相同h=t-step-v;转化一下就是h%2==0.额外要考虑的就是所剩步数必须大于等于当前位置到目标位置最短步数的预留步数,就是t>=step+v;这样进行搜索,如果已走步数大于预留的t则肯定走不到了,意思是说给你3步让你走,可是出发点到目标位置的最短步数为4,这样直接就可以判断走不到了。


#include <stdio.h>
#include <string.h>
#include <math.h>
int flag;
int n,m,p,q,l,f,t;
int book[9][9];
char map[9][9];
 
void dfs(int x,int y,int step)
{
	int k,i,j;
	int tx,ty,v,h;
	int next[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
	if(x==p&&y==q&&step==t)
		flag=1;
	if(flag==1||step>=t)
		return ;
	v=abs(x-p)+abs(y-q);
	h=t-step-v;
	if(h<0||h%2!=0)
		return ;
	for(k=0;k<4;k++)
	{
		tx=x+next[k][0];
		ty=y+next[k][1];
		if(tx<1||tx>n||ty<1||ty>m)
			continue ;
		if(book[tx][ty]==0&&map[tx][ty]!='X')
		{
			book[tx][ty]=1;
			dfs(tx,ty,step+1);
			book[tx][ty]=0;
		}
	}
	return ;
}
 
int main()
{
	int i,j,k;
	while(scanf("%d%d%d",&n,&m,&t),n!=0,m!=0,t!=0)
	{
		flag=k=0;
		for(i=1;i<=n;i++)
		{
			scanf("%s",map[i]+1);
			for(j=1;j<=m;j++)
			{
				if(map[i][j]=='S')
				{
					l=i;
					f=j;
				}
				if(map[i][j]=='D')
				{
					p=i;
					q=j;
				}
				if(map[i][j]=='#')
					k++;
			}
		}
		memset(book,0,sizeof(book));
		book[l][f]=1;
		if(n*m-k>=t)
			dfs(l,f,0);
		if(flag==1)
			printf("YES\n");
		else
			printf("NO\n");
	}
	return 0;

--------------------- 
作者:Robin_yy 
来源:CSDN 
原文:https://blog.csdn.net/ak201605050122/article/details/76423028 
版权声明:本文为博主原创文章,转载请附上博文链接!
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值