http://acm.hdu.edu.cn/showproblem.php?pid=1010
题意:本体的意思是必须在规定的时间内到达指定的地点,不可以多于也不可以少于。
思路就是搜索,但是搜索的话直接暴力肯定会t,所以这里必须要剪枝。
剪枝的方法是奇偶剪枝。
奇偶剪枝是数据结构的搜索中,剪枝的一种特殊小技巧。
现假设起点为(sx,sy),终点为(ex,ey),给定t步恰好走到终点,
s
| ||||
|
| ||||
|
| ||||
|
| ||||
+
|
—
|
—
|
—
|
e
|
如图所示(“|”竖走,“—”横走,“+”转弯),易证abs(ex-sx)+abs(ey-sy)为此问题类中任意情况下,起点到终点的最短步数,记做step,此处step1=8;
s
|
—
|
—
|
—
| |
—
|
—
|
+
| ||
|
|
+
| |||
|
| ||||
+
|
—
|
—
|
—
|
e
|
如图,为一般情况下非
最短路径的任意走法举例,step2=14;
step2-step1=6,偏移路径为6,偶数(易证);
2结论编辑
推广之,若 t-[abs(ex-sx)+abs(ey-sy)] 结果为非偶数(奇数),则无法在t步恰好到达;
返回,false;
反之亦反。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
using namespace std;
int a[4][2]={{1,0},{0,-1},{-1,0},{0,1}};
char map[8][8];
int v[8][8],tt,m,n,ex,ey,flag;
void dfs(int x,int y,int t)
{
int i,j;
if(x==ex&&y==ey)//注意这里 不能使用map[x][y]==D' 具体看下面解释
{
if(t==0)flag=1;
return;
}
if(flag==1)
return;
int tmp;
tmp=t-abs(x-ex)-abs(y-ey);
if(tmp<0||tmp%2!=0)
return;
// printf("%d %d\n",x,y);
for(i=0;i<4;i++)
{
int xx,yy;
xx=x+a[i][0];
yy=y+a[i][1];
if(map[xx][yy]!='X'&&v[xx][yy]==0&&xx>=0&&xx<n&&yy>=0&&yy<m)
{
v[xx][yy]=1;
dfs(xx,yy,t-1);
v[xx][yy]=0;
}
}
}
int main()
{
int i,j,x,y,num;
while(scanf("%d%d%d",&n,&m,&tt)!=EOF)
{
if(n==0&&m==0&&tt==0)
break;
num=0;
memset(v,0,sizeof(v));
flag=0;
// cout<<n<<m<<tt<<endl;
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
cin>>map[i][j];
if(map[i][j]=='S')
{
x=i;
y=j;
}
if(map[i][j]=='D')
{
ex=i;
ey=j;
}
if(map[i][j]=='X')
num++;
}
}
if(n*m-num<tt)
{
printf("NO\n");
continue;
}
v[x][y]=1;
dfs(x,y,tt);
if(flag==0)
{
printf("NO\n");
continue;
}
if(flag)
printf("YES\n");
}
return 0;
}
if(di>=0&&di<n&&dj>=0&&dj<m&&map[di][dj]!='X') { map[di][dj]='X'; dfs(di,dj,cnt+1); map[di][dj]='.'; } 在进行dfs的时候,你首先将map[di][dj]置为了'X',在dfs结束之后再将其还原为'.'。但是此处的map[di][dj]有可能原本是'D'而不是'.',这样一来就会导致map中原本是'D'的元素变成了'.',用if(map[x][y]=='D')作为判断条件也就找不到出口了。 你可以试一试这组样例: 2 2 3 S. D. 具体情况调试一下就清楚了。