hdoj 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): 89317    Accepted Submission(s): 24279


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
 
 
题意:输入n,m,k,n和m代表一个n*m的矩阵,S为起点D为终点,问能否在k步时走到终点;
题解:太坑了,刚开始以为是bfs直接敲出来提交wa了,后来发现题中说的是在第k步时到达终点,
        这就要遍历所有可能的路线了,
        注意此题需要奇偶剪枝,不然会超时(本人亲测)
奇偶剪枝:
/*
*0 1 0 1 0 1
*1 0 1 0 1 0
*0 1 0 1 0 1
*1 0 1 0 1 0
*0 1 0 1 0 1
*1 0 1 0 1 0
*
*如上图所示:
*从0->1和从1->0步数都是奇数
*从0->0和从1->1步数都是偶数
*则当所要求的步数是偶数是我
*们就可以舍去步数是奇数的路
*线,同样,当所要求的步数是
*奇数时,我们可以舍去步数是
*偶数的路线   即判断:
*(x2-x1+y2-y1)&1 是否 ==k&1 
*/

  AC代码:

#include<stdio.h>
#include<string.h>
int x1,x2,y1,y2;
char map[10][10];
int n,m,k,ok;
int move[4][2]={0,1,0,-1,1,0,-1,0};
int judge(int r,int c)
{
	if(map[r][c]=='X'||r<0||r>=n||c<0||c>=m)
	return 0;
	return 1;
}
void dfs(int x,int y,int step)//step记录走的步数 
{
	int i;
	if(ok) return ;//搜索到结果 
	if(step>k) return ;//步数大于k 
	else if(step==k)
	{
		if(x==x2&&y==y2)
		    ok=1;
		return ;
	}
	else
	{
		for(i=0;i<4;i++)
		{
			int tx=x+move[i][0];
			int ty=y+move[i][1];
			if(judge(tx,ty))
			{
				map[x][y]='X';//标记走过的位置 
				dfs(tx,ty,step+1);
				map[x][y]='.';//回溯取消标记 
			}
		}
	}
}
int main()
{
	int i,j,wall;
	while(scanf("%d %d %d",&n,&m,&k),n||m||k)
	{
		ok=0;
		wall=0;
		for(i=0;i<n;i++)
		scanf("%s",map[i]);
		for(i=0;i<n;i++)
		{
			for(j=0;j<m;j++)
			{
				if(map[i][j]=='S')
				{
					x1=i;
					y1=j;
				}	
				else if(map[i][j]=='D')
				{
					x2=i;
					y2=j;
				}
				else if(map[i][j]=='X')
				wall++;
			}
		}
		//前句是奇偶剪枝 ,后一句是判断如果可以走的空地小于要求的步数也不可以 
		if(((x2-x1+y2-y1)&1)!=(k&1)||n*m-wall<=k)
		{
			printf("NO\n");
			continue;
		}
		dfs(x1,y1,0);
		if(ok)
		printf("YES\n");
		else
		printf("NO\n");
	}
	return 0;
}

  

 
posted @ 2015-08-05 19:03  非我非非我  阅读(147)  评论(0编辑  收藏  举报