A - Tempter of the Bone

Subject

The doggie found a bone in an ancient maze, whichfascinated 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 atrap, 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. Atthe beginning, the door was closed and it would open at the T-th second for ashort period of time (less than 1 second). Therefore the doggie had to arriveat the door on exactly the T-th second. In every second, he could move oneblock to one of the upper, lower, left and right neighboring blocks. Once heentered a block, the ground of this block would start to sink and disappear inthe next second. He could not stay at one block for more than one second, norcould he move into a visited block. Can the poor doggie survive? Please helphim. 

*************************************************************************************************************************

Input

The input consists of multiple test cases. The first lineof 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 thedoor will open, respectively. The next N lines give the maze layout, with eachline 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" ifthe 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

 *************************************************************************************************************************

思路就是dfs,简单的去寻找一下就可以了。

 *************************************************************************************************************************

超时代码一代码如下:

#include<iostream>  
#include<algorithm>  
#include<cstdio>  
#include<cstring> 
 
using namespace std;


char map[9][9];

int t,n,m;

bool ans = false;

int fx[4]={-1,0,1,0};
int fy[4]={0,-1,0,1};

int s1,s2;
int d1,d2;

void dfs(int x,int y,int z)
{
	if(z>=t && map[x][y]!='D') 
	   return ;
	   
    for(int i=0;i<4;i++)
	{
		int dx = x+fx[i];
		int dy = y+fy[i];
		if (dx>n || dy>m || dx<=0 || dy<=0||map[dx][dy]=='X'||map[dx][dy]=='#') 
		   continue ;
		if(map[dx][dy]=='D' && z+1==t){
		    ans=true;
		    return ;
	    }
	    if(ans) return ;
		if(map[dx][dy]=='.'){		  	
			map[dx][dy] = '#';
			dfs(dx,dy,z+1);	
			map[dx][dy]='.';
		}
	}
}
int main()
{
	int i,j;
	while(scanf("%d%d%d",&n,&m,&t)!=EOF)
	{
		if(n==m && m==t && t==0)
		   break;
		for( i=1;i<=n;i++)
		{
			for( j=1;j<=m;j++)
			{
				cin>>map[i][j];
				if(map[i][j]=='S'){
					s1 = i;
					s2 = j;
				}
			}
		}
	    ans = false;
		dfs(s1,s2,0);
		if(ans) 
	       printf("YES\n");
		else
		   printf("NO\n");
	} 
	return 0;
}

 *************************************************************************************************************************

不对啊,结果怎么不对啊,提交的答案上去是对的啊,可是提交测试确实超时超时。

运行结果如下:


 *************************************************************************************************************************

此时对于超时,我们应该知道了,代码没有错,但是时间复杂复杂度得控制一下了,也就是说,DFS算法该控制一下循环次数了。

那么这样去搞定呢?

是时候,剪一下枝了。

首先,我们看看地图,总时间为T,墙为X,出发点为S,终点为D,最坑的是D,只开一次。你说气不气?

不过问题在这里,我们得想办法去解决啊,

   剪枝1,如果地图总数 -减去墙X的数目比总时间T还要多,我们直接不要了吧,走了不能还原啊,回不去啊,总会走光的。

   剪枝2,如果剩余时间小于,你到终点的绝对值距离,那也不要了吧!

剪了试试,

超时代码二代码如下:

#include<iostream>  
#include<algorithm>  
#include<cstdio>  
#include<cstring> 
using namespace std;

char map[9][9];
int t,n,m;

bool ans = false;
int fx[4]={-1,0,1,0};
int fy[4]={0,-1,0,1};

int s1,s2;
int d1,d2;

void dfs(int x,int y,int z)
{
	if(z>=t && map[x][y]!='D') 
	   return;
	//到达终点最小时间数 = 走过的时间 - 绝对值距离。 
	int temp=(t-z)-(abs(x-d1)+abs(y-d2));
	if(temp<0)
	{
		return;
	}
    for(int i=0;i<4;i++)
	{
		int dx = x+fx[i];
		int dy = y+fy[i];
		if (dx>n || dy>m || dx<=0 || dy<=0||map[dx][dy]=='X'||map[dx][dy]=='#') 
		   continue ;
		if(map[dx][dy]=='D' && z+1==t){
		    ans=true;
		    return;
	    }
	    if(ans) return ;
		if(map[dx][dy]=='.'){		  	
			map[dx][dy] = '#';
			dfs(dx,dy,z+1);	
			map[dx][dy]='.';
		}
	}
}
int main()
{
	int i,j;
	while(scanf("%d%d%d",&n,&m,&t)!=EOF)
	{
		int ans1=0;
		if(n==m && m==t && t==0)
		   break;
		for( i=1;i<=n;i++)
		{
			for( j=1;j<=m;j++)
			{
				cin>>map[i][j];
				if(map[i][j]=='S'){
					s1 = i;
					s2 = j;
				}
				if(map[i][j]=='X')
				ans1++;
				if(map[i][j]=='D')
				{
				   d1=i;
				   d2=j;
				}
			}
		}
		//地图总数目 - 墙的个数 与 总时间比较 
		if(n*m-ans1<=t)
		{
			printf("NO\n");
			continue;
		}
	    ans = false;
		dfs(s1,s2,0);
		if (ans) 
	       printf("YES\n");
		else
		   printf("NO\n");
	} 
	return 0;
}

 *************************************************************************************************************************

运行结果如下:


还是不够啊,时间还是超时啊,看来的拿出杀手锏了。

 *************************************************************************************************************************

剪枝3 如果减去的时间是奇数,那么直接去掉。

原理如下:

所以我们用一个整数去记录,看如果到达D点,剩余的步数,是不是奇数,(小技巧,&1和%2,优先选择&1,因为机器识别二进制的原因。时间复杂度少一点。)

无论,到达D点的绝对距离,只需要管,到达之后的时间数目,==T,表示刚刚好,%2==0,如果到达之后,还要绕一下,那么步数也是%2==0的。

 *************************************************************************************************************************

改变最后代码如下:

#include<iostream>  
#include<algorithm>  
#include<cstdio>  
#include<cstring> 
using namespace std;

char map[9][9];
int t,n,m;

bool ans = false;
int fx[4]={-1,0,1,0};
int fy[4]={0,-1,0,1};

int s1,s2;
int d1,d2;

void dfs(int x,int y,int z)
{
	if(z>=t && map[x][y]!='D') 
	   return;
	//到达终点之后的最小时间数 = 走过的时间 - 绝对值距离。 
	int temp=(t-z)-(abs(x-d1)+abs(y-d2));
	if(temp<0 || temp&1)
	{
		return;
	}
    for(int i=0;i<4;i++)
	{
		int dx = x+fx[i];
		int dy = y+fy[i];
		if (dx>n || dy>m || dx<=0 || dy<=0||map[dx][dy]=='X'||map[dx][dy]=='#') 
		   continue ;
		if(map[dx][dy]=='D' && z+1==t){
		    ans=true;
		    return;
	    }
	    if(ans) return ;
		if(map[dx][dy]=='.'){		  	
			map[dx][dy] = '#';
			dfs(dx,dy,z+1);	
			map[dx][dy]='.';
		}
	}
}
int main()
{
	int i,j;
	while(scanf("%d%d%d",&n,&m,&t)!=EOF)
	{
		int ans1=0;
		if(n==m && m==t && t==0)
		   break;
		for( i=1;i<=n;i++)
		{
			for( j=1;j<=m;j++)
			{
				cin>>map[i][j];
				if(map[i][j]=='S'){
					s1 = i;
					s2 = j;
				}
				if(map[i][j]=='X')
				ans1++;
				if(map[i][j]=='D')
				{
				   d1=i;
				   d2=j;
				}
			}
		}
		//地图总数目 - 墙的个数 与 总时间比较 
		if(n*m-ans1<=t)
		{
			printf("NO\n");
			continue;
		}
	    ans = false;
		dfs(s1,s2,0);
		if (ans) 
	       printf("YES\n");
		else
		   printf("NO\n");
	} 
	return 0;
}

觉得写得好的,点个赞吧,谢谢,大佬们。毕竟花了不少功夫啊。谢谢。

 *************************************************************************************************************************

转载于:https://www.cnblogs.com/new-zjw/p/8541005.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值