题目链接:点击打开链接
题目大意:输入一个n*m的地图,问从S到D刚好走k步能否成立。
大体思路:BFS是针对最短路径的方法,这道题看似是用BFS,实际上用DFS更好一些。这道题目跟那些DFS不一样的地方是他用到的剪枝方法,叫做奇偶剪枝(如果不用的话就会tle)。
奇偶剪枝
如果只能上下左右走,易得两点间最短距离是横坐标的差的绝对值加上纵坐标的差的绝对值,即lmin=|xi-xj|+|yi-yj|
奇偶剪枝实际上就是用到了一个特性,即:
如果只能上下左右走,那么一个点到另一个点的最短距离,与这个点到达另一个点走的步数的奇偶性必然是相同的,所以如果奇偶性不同就直接不考虑这种情况,把这种情况直接减掉。(实际上剪枝听上去很高级,其实就是把不可能的情况去掉..)
回到这道题目,如果让dfs之后走的坐标设为(xx,yy),D的坐标设为(dx,dy),那么其最短距离就是|xx-dx|+|yy-dy|,走的步数就是k-当前已经走过步数(因为你接下来必须走这么多步到达终点才能yes),如果奇偶性不一样,那么好的,直接拜拜,return掉,因为继续走下去无论中间有多少障碍,他都已经不可能在规定步数的情况下到达D,与其这样还不如早些送他离开。
还有一点就是走完以后一定要把vis[xx][yy]=0...又忘记了很难受...
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<math.h>
using namespace std;
char map[10][10];
int vis[10][10];
int n,m,t,sx,sy,dx,dy,flag,k;
int to[4][2]={1,0,-1,0,0,1,0,-1};
void dfs(int x,int y,int time){
if(x==dx&&y==dy&&time==k){
flag=1;
return;
}
if(flag){
return;
}
int temp=k-time;
int dev=abs(x-dx)+abs(y-dy);
if(dev%2!=temp%2){
return;
}
for(int i=0;i<4;i++){
int xx=x+to[i][0];
int yy=y+to[i][1];
if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&time<=k&&map[xx][yy]!='X'&&!vis[xx][yy]){
vis[xx][yy]=1;
dfs(xx,yy,time+1);
vis[xx][yy]=0;
}
}
}
int main(){
while(~scanf("%d%d%d",&n,&m,&k)&&(n||m||k)){
memset(vis,0,sizeof(vis));
flag=0;
for(int i=1;i<=n;i++){
scanf("%s",map[i]+1);
for(int j=1;j<=m;j++){
if(map[i][j]=='S'){
sx=i,sy=j;
}
if(map[i][j]=='D'){
dx=i,dy=j;
}
}
}
vis[sx][sy]=1;
dfs(sx,sy,0);
if(flag){
printf("YES\n");
}
else{
printf("NO\n");
}
}
return 0;
}