ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

深度优先搜索(DFS)与广度优先搜索(BFS)

2022-03-19 17:01:15  阅读:152  来源: 互联网

标签:优先 int DFS 搜索 && x2 y2 true


       搜索算是一种暴力枚举,但与暴力枚举不同,暴力枚举是将所有可能的答案全部枚举一遍来求得最优解,而搜索是在枚举时跳过不可能出现答案的“死路”。在数据量小时暴力枚举可以作为通解,但数据量一大就很可能超时。如果自己判断出题目是要枚举且没有别的思路,那么可以使用搜索来解决。

     搜索包含深度优先搜索和广度优先搜索,都是从小到大逐渐增加搜索范围。

下方例题使用两种搜索来做

     P1135 奇怪的电梯 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

深度优先搜索(DFS):

#include <bits/stdc++.h>
using namespace std;
int n,a,b,z[203],ans=10000000;//数组z存储上下楼的层数
bool l[203]={false};   //false表示未到达过该楼层
void star(int x,int y)
{
if(y>ans)return;
if(x==b){ans=y;return;}
 l[x]=true;
 if((z[x]+x)<=n&&!l[z[x]+x])star(z[x]+x,y+1);//上楼
 if((x-z[x])>0&&!l[x-z[x]])star(x-z[x],y+1);//下楼
 l[x]=false; //回溯
}
int main()
{std::ios::sync_with_stdio(false);
cin>>n>>a>>b;
for(int i=1;i<=n;i++)
    cin>>z[i];
l[a]=true;
star(a,0);
if(ans==10000000)cout<<"-1";
else cout<<ans;
}

     深度优先搜索总是以选择上楼或下楼优先,一直到当前楼层不能再上楼或再下楼时回到上一次所在楼层,并选择下楼或者在返回上一次所在楼层,直到到达要求的楼层或者将能到达的楼层全部到达过为止,在到达要求楼层时还要比较按钮次数,最后得到最小按钮次数。

广度优先搜索(BFS):

#include <bits/stdc++.h>
using namespace std;
int n,a,b,z[203];//数组z表示上下楼层数
struct node{int x,y;}w;//x表示当前所在楼,y表示按动次数
queue<node>q;
bool l[203]={false};   //false表示未到达过该楼层
int main()
{std::ios::sync_with_stdio(false);
cin>>n>>a>>b;
for(int i=1;i<=n;i++)
    cin>>z[i];
l[a]=true;
q.push((node){a,0});
while(!q.empty())
{w=q.front();q.pop();
if(b==w.x)break;
l[w.x]=true;
if((w.x+z[w.x])<=n&&!l[w.x+z[w.x]])q.push((node){w.x+z[w.x],w.y+1});//上楼
if((w.x-z[w.x])>0&&!l[w.x-z[w.x]])q.push((node){w.x-z[w.x],w.y+1});//下楼
}
if(w.x!=b)cout<<"-1";
else cout<<w.y;
}

        广度优先搜索以按钮次数优先,将上楼和下楼一起进行,到达一个楼层后要等待其他路线全部到达楼层才能继续上下楼,遇到无法上下楼的情况时停止,进行下一个路线,直到到达要求的楼层,且到达后的按钮次数一定是所有路线中最少的。

       但搜索并非万能,在一些题目中使用递推或公式推导来做明显比搜索要快得多。比如下面这个题目。

P1002 [NOIP2002 普及组] 过河卒 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

如果使用深入优先搜索:

#include <iostream>
using namespace std;
bool a[21][21];
int x1,y1,x2,y2,cc=0;
void ss(int x,int y){
    if(x==0&&y==0){cc++;return;}
if(x-1>=0&&!a[x-1][y])ss(x-1,y);
if(y-1>=0&&!a[x][y-1])ss(x,y-1);
}
int main()
{
cin>>x1>>y1>>x2>>y2;
 a[x2][y2]=true;
if(x2-2>=0&&y2+1>=0)a[x2-2][y2+1]=true;//马能到达的坐标
if(x2-2>=0&&y2-1>=0)a[x2-2][y2-1]=true;//true表示马可以到达
if(x2+2>=0&&y2+1>=0)a[x2+2][y2+1]=true;
if(x2+2>=0&&y2-1>=0)a[x2+2][y2-1]=true;
if(x2-1>=0&&y2+2>=0)a[x2-1][y2+2]=true;
if(x2-1>=0&&y2-2>=0)a[x2-1][y2-2]=true;
if(x2+1>=0&&y2+2>=0)a[x2+1][y2+2]=true;
if(x2+1>=0&&y2-2>=0)a[x2+1][y2-2]=true;
ss(x1,y1);cout<<cc;
}

结果就是有两个测试点超时,其中一个测试点的测试数据为

20 20 4 0

看起来数很小,但测试输出为

56477364570

 如果使用递推:

#include <iostream>
using namespace std;
bool a[21][21];
int x1,y1,x2,y2;long long cc=0,ss[21][21];
int main()
{
cin>>x1>>y1>>x2>>y2;
 a[x2][y2]=true;
 ss[0][0]=1;
if(x2-2>=0&&y2+1>=0)a[x2-2][y2+1]=true;
if(x2-2>=0&&y2-1>=0)a[x2-2][y2-1]=true;
if(x2+2>=0&&y2+1>=0)a[x2+2][y2+1]=true;
if(x2+2>=0&&y2-1>=0)a[x2+2][y2-1]=true;
if(x2-1>=0&&y2+2>=0)a[x2-1][y2+2]=true;
if(x2-1>=0&&y2-2>=0)a[x2-1][y2-2]=true;
if(x2+1>=0&&y2+2>=0)a[x2+1][y2+2]=true;
if(x2+1>=0&&y2-2>=0)a[x2+1][y2-2]=true;
for(int i=0;i<=x1;i++){                //递推
for(int j=0;j<=y1;j++){                  
        if(a[i][j])continue;
    if(i-1>=0)ss[i][j]+=ss[i-1][j];
if(j-1>=0)ss[i][j]+=ss[i][j-1];
}}
cout<<ss[x1][y1];
}

结果全部通过

对于两种方法各自通过测试数据的时间:当数据量不是很大时,通过时间几乎一样。但数据量变大时,递推比搜索更快,且差距逐渐增大。

标签:优先,int,DFS,搜索,&&,x2,y2,true
来源: https://blog.csdn.net/z_10001/article/details/123593933

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有