【暖*墟】 #BFS# 广搜技巧与优化

BFS 广度优先搜索(队列)


目录

一. 基本实现

二. 双端队列

普通队列用于边权为定值的最短路搜索。

         双端队列可以进行边权为1/0的最短路搜索。

【例题】洛谷 p2243 电路维修

三. Hash判重

1、哈希表的特征

2、哈希表的实现方法:拉链法

3、Hash的应用

4、散列法

【Hash表的常见构造方法】

【例题】洛谷 p2730 魔板


一. 基本实现

a .首先选择一个顶点作为起始结点,并将其染成灰色,其余结点为白色。

b. 将起始结点放入队列中。 并找出所有与之邻接的结点。

c. 从队列首部选出一个顶点,将找到的邻接结点放入队列尾部,

将已访问过结点涂成黑色。如果顶点的颜色是灰色,表示已经放入了队列,

如果顶点的颜色是白色,表示还没有发现 d. 按照同样的方法处理队列中的下一个结点。

基本就是出队的顶点变成黑色,在队列里的是灰色,还没入队的是白色。

例如,从顶点1开始进行广度优先搜索:

  1. 初始状态,从顶点1开始,队列={1}
  2. 访问1的邻接顶点,1出队变黑,2,3入队,队列={2,3,}
  3. 访问2的邻接结点,2出队,4入队,队列={3,4}
  4. 访问3的邻接结点,3出队,队列={4}
  5. 访问4的邻接结点,4出队,队列={ 空} 结点5对于1来说不可达。

 

二. 双端队列

普通队列用于边权为定值的最短路搜索。

且每次到达都是最优的决策(不用取min)。

因为所有状态按照 入队的先后顺序 具有 层次单调性,每次扩展,都往外走一步,

满足从起始到该状态的最优性(不用取min/也不用比大小,如果如此失去了意义)。

双端队列可以进行边权为1/0的最短路搜索。

对于一条边 u 到 v ,如果此边权值为0,我们将它 push_front(v) ,否则 push_back(k),

每次取队首,这样我们保证了单调性(即每次优先选择最优的)。

注意细节:把某一方格对角两点的连线看成边,若和原状态匹配边权为0,否则为1。

我们放入队列里的还有u,这样才能做到将每次取出的时候更新,

也就是说在队列中放入二元组(u,v)。复杂度:O(r*c)。


【例题】洛谷 p2243 电路维修

有一天 Mark 和James 的飞行车没有办法启动了,经过检查发现原来是电路板的故障。

飞行车的电路板设计很奇葩,如下图所示:

对于每组测试数据,在单独的一行输出一个正整数,表示所需的缩小旋转次数。

如果无论怎样都不能使得电源和发动机之间连通,输出 NO SOLUTION。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<deque> //双端队列
using namespace std;
 
const int MAXX=550;
int dis[MAXX][MAXX];
bool vis[MAXX][MAXX],Map[MAXX][MAXX];
int dx[4]={1,-1,1,-1};
int dy[4]={1,-1,-1,1}; //矩形中的边的扩展方向
char ss[MAXX];
int t,r,c; 
 
inline bool checks(int x,int y){ //检查是否到边界
    if(x>=1&&y>=1&&x<=r+1&&y<=c+1) 
    	return true;
    return false;
}
 
inline int edges(int x,int xx,int y,int yy){
    if((xx<x&&yy<y)||(xx>x&&yy>y))
    	return !Map[min(x,xx)][min(y,yy)];
    else return Map[min(x,xx)][min(y,yy)];
}
 
inline void bfs(){
    Map[0][0]=1; //广搜起点
    deque< pair < pair<int ,int> ,p
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值