HDU 1010 比较坑人的一道搜索题

本人当初只是想到用搜索做,上手就是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;

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值