题目大意:给一张迷宫地图,看看是否有等够在给的时间刚好到达终点,并且走过的不能重复走,记住,是刚好到达!!!

思路:搜索题,一开始只是轻微地作找到方案,作标记flag的剪枝,发现超时,原来还要奇偶剪枝,就是你一步一步走,如果你的位置到终点最小路程与剩余时间做差刚好是个奇数时,就要去掉。可能你会想,我们多走几格不就好了?但是你可以在稿纸上模拟一下,可以知道任何到达终点的路程(切记不能重复)刚好和最短路程的奇偶性一样。这点大牛们已经帮我们证明过了,当然你数学够6的话可以试试,反正身为菜鸟的我是不会啦,言归正传,剩下的就是搜索的基本思路啦,不知道那些排行榜的0ms的怎么写得(膜拜!),我的只能109ms,大佬又发现能再优化的一定告诉我哈!

代码如下:

#include<stdio.h>
#include<string.h>
#include<math.h>
int book[15][15],n,m,flag,rx,ry;
char map[15][15];
int next[4][2]={
	{0,1},{1,0},{0,-1},{-1,0}
};

bool pan(int x,int y)
{
	if(x<0||x>=n||y<0||y>=m||map[x][y]=='X')
		return false;
	return true;
}

void dfs(int time,int x,int y)
{
	if(time<0)
		return ;
	if(time==0)
	{
		if(map[x][y]=='D')
		{
			flag=1;
			return ;
		}
		return ;
	}
	int a,b,i;
	a=abs(x-rx);
	b=abs(y-ry);
	if(time-a-b<0||(time-a-b)%2)  //如果剩余的实践无法达到终点或者达到终点后还有时间就去掉(奇偶剪枝)
		return ;
	for(i=0;i<4;i++)
	{
		a=x+next[i][0];
		b=y+next[i][1];
		if(pan(a,b) && !book[a][b])
		{
			book[a][b]=1;
			dfs(time-1,a,b);
			book[a][b]=0;
		}
		if(flag) return ;  //如果已经找到方案就不用再搜了(剪枝)
	}
	return ;
}

int main()
{
	int i,j,time,x,y,p;
	while(~scanf("%d%d%d",&n,&m,&time) && (n||m||time))
	{
		getchar();
		memset(book,0,sizeof(book));
		memset(map,0,sizeof(map));
		for(i=p=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')
			{
				x=i,y=j;
			}
			else if(map[i][j]=='D')
			{
				rx=i,ry=j;
			}
			else if(map[i][j]=='X')
			{
				p++;
			}
		if(n*m-p-time<=0)   //剪枝,容易遗忘等于的情况
		{
			printf("NO\n");
			continue;
		}
		book[x][y]=1;
		flag=0;
		dfs(time,x,y);
		if(flag)
			printf("YES\n");
		else
		printf("NO\n");
	}
	return 0;
}