奇偶剪枝 奇数减去奇数是偶数,偶数减去偶数也是偶数,本题的一个剪枝用到这个技巧,就是,规定的步数与最短的步数 奇偶性相同的话,就可以规定的步数正好走到终点
//这道题需要大量的剪枝过程,少一个都可能会报错bn
/*
设起点坐标是bx,by;终点坐标是ex,ey;
最短路径是abs(bx-ex)+abs(by-ey)
但是我们可以很显然的看出来,无论是走,我们的步数肯定比最短路径数多一个偶数
所以,简化的第一点来了:如果题目中输入的步数比最短路径数多得是一个奇数,那么我们永远也不可能走到,所以直接输出NO;
步数大于给定 ,直接输出NO
提前退出,避免超时。DFS是用递归实现的,那么如果我们找到了终点并且路数也符合,
不能只是让指示变量变值那么简单我们要在每次递归返回后面再加上一个判断,目的是终止查找;
如果不这样做,就算找到了结果是YES我们也必须等到整个图全部被扫描完才可以结束程序
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char map[8][8],book[8][8];
int n,m,t,flag,a,b,c,d;
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
void dfs(int x,int y,int step)
{
if(map[x][y] == 'D'){
if(step == t)
flag = 1;
return;
}
//剪枝过程,避免了大量运算
int tmp = t - step - abs(c-x) - abs(d-y);
if(tmp < 0 || tmp&1)
{
return;
}
if(step > t)
return;
for(int i=0;i<4;i++){
int tx = x+dir[i][0];
int ty = y+dir[i][1];
if(tx>=0&&tx<n&&ty>=0&&ty<m&&map[tx][ty]!='X'&&!book[tx][ty])
{
book[x][y]=1;
dfs(tx,ty,step+1);
if(flag)
return;
book[tx][ty]=0;
}
}
}
int main()
{
while(cin>>n>>m>>t){
if(n==0&&m==0&&t==0)
break;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++){
cin>>map[i][j];
if(map[i][j] == 'S') //标记开始坐标
a=i,b=j;
if(map[i][j] == 'D') //标记终止坐标
c=i,d=j;
}
memset(book , 0, sizeof(book));
flag = 0;
dfs(a,b,0);
if(flag) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}