HDU1010:Tempter of the Bone(DFS)

Problem Description
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

两处剪枝:

1.给定的步数过大

2.给定步数-当前步数-(当前距离终点距离)=正偶数(保证按要求刚好达到目的地)

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>

using namespace std;

char map[10][10];
int book[10][10];
int row,column,cnt;
int flag;
int wall; 
int sx,sy,ex,ey;
int dire[4][2]={{-1,0},{1,0},{0,-1},{0,1}};

void dfs(int x,int y,int step)

{
	//不需要继续搜索了 
	if(flag)
		return;
	//达到目的地 
	if(x==ex&&y==ey)
	{
		//如果当前步数等于要求步数,flag=1;
		//否则,返回 
		if(step==cnt) 
			flag=1;

		return ;

	}

	

	int dx=abs(ex-x);
	int dy=abs(ey-y);
//剪枝2。要求的步数-已经走的步数-(当前位置和目的位置的距离)
//必须是一个正的偶数。
//负值代表走不到目的地,奇数代表无法刚好走到目的地	
	if((cnt-step-(dx+dy))%2!=0 || dx+dy>cnt-step)
		return;

//进行下一步搜索 
	for(int i=0;i<4;i++)
	{
		int nx=x+dire[i][0];
		int ny=y+dire[i][1];

		if(nx>row||nx<1||ny>column||ny<1)
		continue;

		if(!book[nx][ny]&&map[nx][ny]!='X')//注意是!='X',而非=='.' 
		{
			book[nx][ny]=1;
			dfs(nx,ny,step+1);
			book[nx][ny]=0;
		}

	}

	return;

}

int main()

{

	while(cin>>row>>column>>cnt,row+column+cnt)

	{

		memset(book,0,sizeof(book));

		flag=0;

		wall=0;//统计障碍物的数量 

		for(int i=1;i<=row;i++)
		for(int j=1;j<=column;j++)
		{
			cin>>map[i][j];

			if(map[i][j]=='S')
			{	
				sx=i;
				sy=j;
			}

			if(map[i][j]=='D')
			{
				ex=i;
				ey=j;
			}

			if(map[i][j]=='X')
			wall++; 

		 } 

		 
		//剪枝1,如果给定的步数(时间)加上障碍物大于图的点的数量
		//则输出NO,因为还至少含有S和D。 
		 if(wall+cnt>=row*column) 
		{
			cout<<"NO"<<endl;
			continue;

		}

		 //开始深搜的点进行标记 
		 book[sx][sy]=1;
		
		//开始深搜 
		 dfs(sx,sy,0);

		 if(flag==1)
			cout<<"YES"<<endl;

		 else 
			 cout<<"NO"<<endl;

	}

	return 0;

}


你可能感兴趣的:(DFS)