奇偶剪枝:
是数据结构的搜索中,剪枝的一种特殊小技巧。
现假设起点为(sx,sy),终点为(ex,ey),给定t步恰好走到终点,
s | ||||
| | ||||
| | ||||
| | ||||
+ | — | — | — | e |
如图所示(“|”竖走,“—”横走,“+”转弯),易证abs(ex-sx)+abs(ey-sy)为此问题类中任意情况下,起点到终点的最短步数,记做step,此处step1=8;
s | — | — | — | |
— | — | + | ||
| | + | |||
| | ||||
+ | — | — | — | e |
如图,为一般情况下非最短路径的任意走法举例,step2=14;
step2-step1=6,偏移路径为6,偶数(易证);
故,若t-[abs(ex-sx)+abs(ey-sy)]结果为非偶数(奇数),则无法在t步恰好到达;
返回,false;
反之亦反。
上面借鉴了! http://www.cnblogs.com/zhourongqing/archive/2012/04/28/2475684.html 感谢!!!
#include<iostream>
#include<math.h>
using namespace std;
int f,n,m,t,sx,sy,dx,dy;
char a[10][10];
int d[4][2]={0,1,1,0,0,-1,-1,0};//代表四个方向!
void dfs(int x,int y,int t)
{
if(f==1) return ;
if(t<abs(dx-x)+abs(dy-y)||(t-abs(dx-x)-abs(dy-y))%2) return ;
//剪枝,如果剩余时间还大于两点的路径;或剩余时间减去两点的值是偶数的话就可以继续搜索;
else if(t==0)
{ // 如果时间等于零了,讨论;
if(dx==x&&dy==y)
{
f=1;return ;
}
else
return ;
}
else //对四个方向进行深搜;
{
for(int i=0;i<4;i++)
{
int xx=x+d[i][0];int yy=y+d[i][1];
if((xx>0&&xx<=n&&yy>0&&yy<=m)&&(a[xx][yy]=='.'||a[xx][yy]=='D'))
//判断是不是墙!
{
a[xx][yy]='X';
dfs(xx,yy,t-1);
a[xx][yy]='.';
}
}
}
return ;
}
int main()
{
int i,j;
while(cin>>n>>m>>t&&(n||m||t))
{
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
cin>>a[i][j];
if(a[i][j]=='S')
{
sx=i;sy=j;
}
if(a[i][j]=='D')
{
dx=i;dy=j;
}
}
f=0;
dfs(sx,sy,t);
if(f==1)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}