广搜(bfs)

定义

广度优先算法,简称BFS.是一种图形搜索演算法,简单的说,BFS是从根节点开始,沿着树的宽度遍历树的节点,如果发现目标,终止.

与dfs的相似之处与不同

结合深搜理解

相同点:都是将所有的情况遍历

不同之处:dfs是一条路走到死,但是bfs则是放眼所有能到达的地方

bfs的特点也决定了bfs的使用范围

往往bfs比dfs更加高效

比如

0 0 0
0 0 0
0 0 0

我们从左上角遍历到右上角,最少需要多少步(上下左右)?

比较dfs bfs

dfs:所有的路径都要尝试一遍,效率极其低

bfs:我们将所有能到达的地方都存入队列,发现只要4就可以找出答案,相对于dfs效率大大提升

所以

如果将路径列为树的话,那么答案相对深度较小,就适合使用bfs

例题

电路维修

思路:

最短路

明显的最短路

很显然,对于

/

我们从左上到右下耗费的代价是1

否则为0

\

我们从右上到左下耗费的代价是1

否则为0

我们是一定不会利用一个导线1次以上的

那么我们只要建,左上到右下,右上到左下的边,利用最短路就行了

bfs

bfs也差不多

我们以代价为树的深度

我们将对应的代价能到达的区域存入队列,当然,如果之前走过就没有必要再走一遍了

如果搜到了终点就是最优解

#include<bits/stdc++.h>
using namespace std;
struct Jack{
int next,last,ans,x,y,c;
}f[5000000];
bool vis[5000000];
int n,m,tot=0,ed;
inline void put(int x,int y,int c){
f[++tot].x=x;
f[tot].y=y;
f[tot].c=c;
f[tot].next=f[x].last;
f[x].last=tot;
}
inline void search( ){
int i,j,x,y,c;
for(i=1;i<=ed;i++)f[i].ans=0xffffff;
deque<int>q;
q.push_front(1);
vis[1]=0;
f[1].ans=0;
while(!q.empty( )){
x=q.front( );q.pop_front( );
for(i=f[x].last;i>=1;i=f[i].next){
y=f[i].y;c=f[i].c;
if(f[x].ans+c<f[y].ans){
f[y].ans=f[x].ans+c;
if(!vis[y]){
vis[y]=1;
if(c==1)q.push_back(y);
else q.push_front(y);
}
}
}
vis[x]=0;
}
}
int main( ){
std::ios::sync_with_stdio(false);
cin>>n>>m;
char s[510];
int i,j,x1,x2,x3,x4;
ed=(n+1)*(m+1);
for(i=1;i<=n;i++){
cin>>s+1;
for(j=1;j<=m;j++){
x1=(m+1)*(i-1)+j;x2=(m+1)*i+j+1;x3=x1+1;x4=x2-1;
if(s[j]=='\\'){
put(x1,x2,0);
put(x2,x1,0);
put(x3,x4,1);
put(x4,x3,1);
}else{
put(x1,x2,1);
put(x2,x1,1);
put(x3,x4,0);
put(x4,x3,0);
}
}
}
search( );
if(f[ed].ans==0xffffff)cout<<"NO SOLUTION"<<endl;
else cout<<f[ed].ans<<endl;
}

魔板

思路:

我们以次数为树的深度,建立一颗树,进行bfs遍历即可

#include<bits/stdc++.h>
using namespace std;
string want;
map<string,string>m;
queue<string>q;
inline void A(string a){
string s=a;
int i;
for(i=0;i<4;i++)swap(s[i],s[7-i]);
if(!m.count(s)){
m[s]=m[a]+'A';
q.push(s);
}
}
inline void B(string a){
string s=a;
s[0]=a[3],s[1]=a[0],s[2]=a[1],s[3]=a[2],s[4]=a[5],s[5]=a[6],s[6]=a[7],s[7]=a[4];
if(!m.count(s)){
m[s]=m[a]+'B';
q.push(s);
}
}
inline void C(string a){
string s=a;
s[1]=a[6];s[2]=a[1];s[5]=a[2];s[6]=a[5];
if(!m.count(s)){
m[s]=m[a]+'C';
q.push(s);
}
}
inline void bfs(){
q.push("12345678");
m["12345678"]="";
while(!q.empty( )){
A(q.front( ));
B(q.front( ));
C(q.front( ));
if(m.count(want)!=0){
cout<<m[want].size( )<<endl<<m[want];
return;
}
q.pop( );
}
}
int main( ){
char a1;
for(int i=0;i<8;i++)cin>>a1,want+=a1,getchar();
bfs( );
}

走马

思路:

和平时的走马差不多

但是数据庞大,怎么办呢?

这时就引入双端队列,从终点和起点同时进行bfs遍历,如果重复到达一个点,就返回值

#include <bits/stdc++.h>
using namespace std;
struct node{
int x,y,s;
};
queue<node>q;
int T,n,sx,sy,ex,ey;
int b[111][111];
int dx[8] = {1,1,-1,-1,2,2,-2,-2},dy[8]={2,-2,2,-2,1,-1,1,-1};
int main( ){
cin>>T;
while(T--){
while(!q.empty( ))q.pop( );
q.pop( );
cin>>n>>sx>>sy>>ex>>ey;
memset(b,0,sizeof(b));
node a;
a.x=sx,a.y=sy,a.s=0;
q.push(a);
b[sx][sy]=1;
do{
int f=0;
a=q.front( );
if(a.x==ex&&a.y==ey){
cout<<a.s<<endl;
f = 1;
}
if(f) break;
for(int v = 0; v < 8; v++){
int nx = a.x + dx[v] , ny = a.y + dy[v];
if(!b[nx][ny] && nx < n && nx >= 0 && ny < n && ny >= 0){
node c;
c.x = nx , c.y = ny , c.s = a.s + 1;
q.push(c);
b[nx][ny] = 1;
}
}
q.pop();
}while(!q.empty());
}
}

总结

bfs常规思路:

我们通常是通过答案建树,然后bfs遍历这棵树,找到目标就输出,根据bfs的性质,此时一定是最优的

双端队列剪枝:

双端队列,很显然,深度越深状态越多,状态越多时间复杂度越大,双端队列也是靠这个实现的

如果我们同时知道目标和起点,那我们可以通过分别对目标,起点进行bfs遍历,找到共同点就返回答案,达到剪枝效果

浅谈bfs的更多相关文章

  1. 浅谈DFS,BFS,IDFS,A*等算法

    搜索是编程的基础,是必须掌握的技能.--王主任 搜索分为盲目搜索和启发搜索 下面列举OI常用的盲目搜索: 1.dijkstra 2.SPFA 3.bfs 4.dfs 5.双向bfs 6.迭代加深搜索( ...

  2. 虚拟化构建二分图(BZOJ2080 题解+浅谈几道双栈排序思想的题)

    虚拟化构建二分图 ------BZOJ2080 题解+浅谈几道双栈排序思想的题 本题的题解在最下面↓↓↓ 不得不说,第一次接触类似于双栈排序的这种题,是在BZOJ的五月月赛上. [BZOJ4881][ ...

  3. 浅谈 Fragment 生命周期

    版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Fragment 文中如有纰漏,欢迎大家留言指出. Fragment 是在 Android 3.0 中 ...

  4. 浅谈 LayoutInflater

    浅谈 LayoutInflater 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/View 文中如有纰漏,欢迎大家留言指出. 在 Android 的 ...

  5. 浅谈Java的throw与throws

    转载:http://blog.csdn.net/luoweifu/article/details/10721543 我进行了一些加工,不是本人原创但比原博主要更完善~ 浅谈Java异常 以前虽然知道一 ...

  6. 浅谈SQL注入风险 - 一个Login拿下Server

    前两天,带着学生们学习了简单的ASP.NET MVC,通过ADO.NET方式连接数据库,实现增删改查. 可能有一部分学生提前预习过,在我写登录SQL的时候,他们鄙视我说:“老师你这SQL有注入,随便都 ...

  7. 浅谈WebService的版本兼容性设计

    在现在大型的项目或者软件开发中,一般都会有很多种终端, PC端比如Winform.WebForm,移动端,比如各种Native客户端(iOS, Android, WP),Html5等,我们要满足以上所 ...

  8. 浅谈angular2+ionic2

    浅谈angular2+ionic2   前言: 不要用angular的语法去写angular2,有人说二者就像Java和JavaScript的区别.   1. 项目所用:angular2+ionic2 ...

  9. iOS开发之浅谈MVVM的架构设计与团队协作

    今天写这篇博客是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇博客的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦 ...

随机推荐

  1. Java实现 蓝桥杯VIP 算法提高 字符串跳步

    问题描述 给定一个字符串,你需要从第start位开始每隔step位输出字符串对应位置上的字符. 输入格式 第一行一个只包含小写字母的字符串. 第二行两个非负整数start和step,意义见上. 输出格 ...

  2. java实现第三届蓝桥杯机器人行走

    机器人行走 [编程题](满分18分) 某少年宫引进了一批机器人小车.可以接受预先输入的指令,按指令行动.小车的基本动作很简单,只有3种:左转(记为L),右转(记为R),向前走若干厘米(直接记数字). ...

  3. 对LinkedList源码的一些个人理解

    由于转行的原因,最近打算开始好好学习,昨天看到了部分的LinkedList源码,并且看了一点数据结构的视频,现总结部分自己的心得体会,以供后期给现在的自己拍砖~ 双向链表每一个元素都有数据本身加指向前 ...

  4. 数据结构&算法

    20个最常用.最基础数据结构与算法: 10个数据结构:数组.链表.栈.队列.散列表.二叉树.堆.跳表.图.Trie 树. 10个 算法      :递归.排序.二分查找.搜索.哈希.贪心.分治.回溯. ...

  5. HDFS ha 格式化报错:a shared edits dir must not be specified if HA is not enabled.

    错误内容: Formatting using clusterid: CID-19921335-620f-4e72-a056-899702613a6b2019-01-12 07:28:46,986 IN ...

  6. 环境篇:CM+CDH6.3.2环境搭建(全网最全)

    环境篇:CM+CDH6.3.2环境搭建(全网最全) 一 环境准备 1.1 三台虚拟机准备 Master( 32g内存 + 100g硬盘 + 4cpu + 每个cpu2核) 2台Slave( 12g内存 ...

  7. window.open打开新的独立页面

    如下所示的代码: window.open('xxxxx.html', '_blank', 'height=100, width=400, top=0, left=0, toolbar=no, menu ...

  8. ClientDataSet训练之1

    在做平面文件数据集时(ClientDataSet),需要引用单元,  uses Midaslib //D7,ClientDataSet选择文件(添加数据集) //为何D10.3.2不可右键添加数据集呢 ...

  9. Excel常用公式大全

    公式是单个或多个函数的结合运用. AND “与”运算,返回逻辑值,仅当有参数的结果均为逻辑“真(TRUE)”时返回逻辑“真(TRUE)”,反之返回逻辑“假(FALSE)”. 条件判断 AVERAGE ...

  10. 【JMeter_16】JMeter逻辑控制器__随机控制器<Random Controller>

    随机控制器<Random Controller> 业务逻辑: 当每次执行到该逻辑控制器时,随机挑选控制器下的任意一个子节点<取样器.逻辑控制器> Ignore sub-cont ...