本人当初只是想到用搜索做,上手就是BFS结果WA了,后来反应过来只能用DFS来做
提交了21次,全TLE,后来在多次努力下找到了大量的陷阱,为还在为此题困扰的人指指路
1.奇偶剪枝
很简单的一个概念
设起点坐标是bx,by;终点坐标是ex,ey;
最短路径是abs(bx-ex)+abs(by-ey)
但是我们可以很显然的看出来,无论是走,我们的步数肯定比最短路径数多一个偶数
所以,简化的第一点来了:如果题目中输入的步数比最短路径数多得是一个奇数,那么我们永远也不可能走到,所以直接输出NO;
2.路径剪枝
在DFS当前的过程的路数中一旦大于等于要求的步数并且还没有找到终点,直接输出NO
3.最让人后怕的一点
我从自学DFS以来一直没有注意到有一点非常的害怕,DFS是用递归实现的,那么如果我们找到了终点并且路数也符合,不能只是让指示变量变值那么简单
我们要在每次递归返回后面再加上一个判断,目的是终止查找,如果不这样做,就算找到了结果是YES我们也必须等到整个图全部被扫描完才可以结束程序
自然而然就会TLE了
附上AC代码
#include"iostream"
#include"cstdio"
#include"cstring"
using namespace std;
char map[10][10];
int book[10][10];
int n,m,t;
int flag=0;
int nextk[4][2]={{0,1},{1,0},{-1,0},{0,-1}};
int bx,by;
int ex,ey;
int w;
void dfs(int x,int y,int len)
{
int dx,dy;
for(int i=0;i<=3;i++)
{
dx=x+nextk[i][0];
dy=y+nextk[i][1];
if(dx==ex&&dy==ey&&t==len+1)
{
flag=1;
return ;
}
if(len>=t) //路径剪枝
{
return ;
}
else
{
if(dx<1||dx>n||dy<1||dy>m||map[dx][dy]=='X')
{
continue;
}
else
{
if(book[dx][dy]==0&&map[dx][dy]=='.')
{
book[dx][dy]=1;
dfs(dx,dy,len+1);
if(flag==1) //一定要记住要返回
{
return ;
}
book[dx][dy]=0;
}
}
}
}
}
int main()
{
while(1)
{
flag=0;
memset(book,0,sizeof(book));
memset(map,0,sizeof(map));
cin>>n>>m>>t;
if(n==0&&m==0&&t==0)
{
break;
}
else
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>map[i][j];
if(map[i][j]=='S')
{
bx=i;
by=j;
}
if(map[i][j]=='D')
{
ex=i;
ey=j;
}
}
}
w=abs(ex-bx)+abs(ey-by);
if((t-w)%2==1); //奇偶剪枝
else
{
book[bx][by]=1;
dfs(bx,by,0);
}
if(flag==1)
{
cout<<"YES"<<endl;
}
else
{
cout<<"NO"<<endl;
}
}
}
return 0;
}