深搜与广搜(2)

上次我们说到了深搜

这次我们来讲讲广搜。
广搜原理
广搜,顾名思义,是多管齐下、广撒网的一种搜索方法
  如果广搜是一个人,那么她一定很贪心,而且喜新厌旧!她从一点出发去旅游,先把与起点相邻的地方全部游览一遍,然后再把与她刚游览过的景点相邻的景点全都游览一边……一直这样,直至所有的景点都游览一遍。
  广搜属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。类似树的按层遍历,其过程为:首先访问初始点Vi,并将其标记为已访问过,接着访问Vi的所有未被访问过可到达的邻接点Vi1、Vi2…Vit,并均标记为已访问过,然后再按照Vi1、Vi2…Vit 的次序,访问每一个顶点的所有未被访问过的邻接点,并均标记为已访问过,依此类推,直到图中所有和初始点Vi有路径相通的顶点都被访问过为止。

我们来举一个栗子: 看洛谷的p1135奇怪的电梯

传送门:https://www.luogu.com.cn/problem/P1135#submit

其间这道题用dfs,bfs(dp),Bellman-Ford,Floyd,spfa,Dijkstra 都可以做

但我们讲的就是广搜嘛

讲解如下:

BFS——广度优先搜索

用一个队列,维护节点和步数。

开始入队(A,0),然后把上、下入队(合法的话),直到第一次出现 B,其实就是不记录 dis 还不排序的 Dijkstra,记得打标记。

正确性:由于边权全部相等(都是 11),不需要用堆来进行排序(Dijkstra),直接用队列即可。

时间复杂度 O(n),代码几乎同 SPFA(仅实现不同),是 Dijkstra 去掉堆优化(log n)的复杂度。

代码如下:

#include<bits/stdc++.h>
int n,a,b,k[201];
bool f,u[201];//u 是标记
int ri(){
	int x=0;
	char c=getchar(),f=1;
	while(c<'0'||c>'9'){
		if(c=='-')
			f=-f;
		c=getchar();
	}
	while(c<='9'&&c>='0')
		x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
struct node{
	int x,y;
};
std::queue<node>q;
int bfs(){
	q.push(node{a,0});//入队
	u[a]=1;
	while(!q.empty()){
		int x=q.front().x,y=q.front().y;
		q.pop();
		if(x==b)
			return y;//到了 B
		int xn=x+k[x],yn=y+1;
		if(xn<=n&&xn>0&&!u[xn])//上
			q.push(node{xn,yn}),u[xn]=1;
		xn-=2*k[x];
		if(xn<=n&&xn>0&&!u[xn])//下
			q.push(node{xn,yn}),u[xn]=1;
	}
	return-1;
}
int main(){
	n=ri(),a=ri(),b=ri();
	for(int i=1;i<=n;i++)
		k[i]=ri();
	printf("%d",bfs());
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值