题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1010
题意:有一只小狗被困在迷宫里面了,迷宫用S(起点)、D(出口)、X(墙)、.(过道)组成,小狗每秒移动一格,出去的条件是在正好t秒时走到D处,而且每个点上只能呆一秒,不能走已经走过的路。
Sample Input
4 4 5
S.X.
..X.
..XD
....
3 4 5
S.X.
..X.
...D
0 0 0
Sample Output
NO
YES
题解:
注意,这道题目是要恰好t时间到达,并不是在t时间内到达......
思路:剪枝+dfs
第一个剪枝我们可以想到,当剩下的步数大于剩下的时间的时候,狗是不能走到的;
接下来我们来第二个剪枝:
我们把map的奇偶性以01编号:
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
我们发现从0走一步一定走到1,从1走一步一定走到0。
也就是说,如果当前的狗所在的坐标与D的坐标奇偶性不一样,那么狗需要走奇数步。
同理,如果狗所在坐标与D的坐标奇偶性一样,那么狗需要走偶数步数。
也就是说,狗的坐标x、y的和对2取余是它的奇偶性,D点x y的和对2取余是D的奇偶性。两个奇偶性一加再对2取余,拿这个余数去与剩下时间对2取余的余数作比较即可。
代码:#include <iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int n,m,t,ax,ay,bx,by;
bool flag;
char map[10][10];
int vis[10][10];
int k[4][2]={1,0,-1,0,0,1,0,-1};//这串数组意义需要理解
void dfs(int x,int y,int count)
{
if(x==bx && y==by) //能到达的条件
{
if(count==t)
flag=true;
return ;
}
if(count>=t) //不能到达的条件
{
return;
}
if(map[x][y]!='X')
{
for(int i=0;i<4;i++)
{
int mx=x+k[i][0];//k数组的利用
int my=y+k[i][1];
if(mx>=0 && mx<n && my>=0 && my<m && map[mx][my]!='X' && !vis[mx][my])
{
vis[mx][my]=1;
dfs(mx,my,count+1);
vis[mx][my]=0;
if(flag) //注意,在找到了目标之后,就不需要再找!以往编写dfs时,没有注意这点
return;
}
}
}
}
int main()
{
while(scanf("%d %d %d",&n,&m,&t)!=EOF && n+m+t>0)
{
for(int i=0;i<n;i++)
{
getchar(); //读回车
for(int j=0;j<m;j++)
{
scanf("%c",&map[i][j]);
if(map[i][j]=='S') //记入起点坐标
{
ax=i;
ay=j;
}
if(map[i][j]=='D') //记入终点坐标
{
bx=i;
by=j;
}
}
}
getchar(); //读回车
memset(vis,0,sizeof(vis));
if(abs(ax-bx)+abs(ay-by)>t || (ax+bx+ay+by+t)%2==1) //剪枝
{
printf("NO\n");
continue;
}
int count=0;
vis[ax][ay]=1; //起点坐标已经走过,不能再走
flag=false;
dfs(ax,ay,count); //进行dfs
if(flag)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}