BFS广度优先算法

广度优先:每次都尝试访问同一层的节点。 如果同一层都访问完了,再访问下一层。
这样做的结果是,BFS 算法找到的路径是从起点开始的 最短 合法路径。

在 BFS 结束时,每个节点都是通过从起点到该点的最短路径访问的。

算法过程可以看做是图上火苗传播的过程:
最开始只有起点着火了,在每一时刻,有火的节点都向它相邻的所有节点传播火苗。

模板

	q.push(head);
	while(!q.empty()){
		temp=q.front();
		q.pop();
		if(temp为目标状态)
			输出或记录
		if(temp不合法){
			continue;
		if(temp合法)
			q.push(temp+符合题意的数据)
		
	}

例题

Catch That Cow

https://vjudge.csgrandeur.cn/problem/POJ-3278#author=0

题面

Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a point N (0 ≤ N ≤ 100,000) on a number line and the cow is at a point K (0 ≤ K ≤ 100,000) on the same number line. Farmer John has two modes of transportation: walking and teleporting.

  • Walking: FJ can move from any point X to the points X - 1 or X + 1 in a single minute
  • Teleporting: FJ can move from any point X to the point 2 × X in a single minute.

If the cow, unaware of its pursuit, does not move at all, how long does it take for Farmer John to retrieve it?

输入
Line 1: Two space-separated integers: N and K
输出
Line 1: The least amount of time, in minutes, it takes for Farmer John to catch the fugitive cow.

题意

输入n和k表示农夫和牛的位置,n和k在区间【0,100000】间
农夫有三种方式进行移动,每种方式需要的时间相同,都是一分钟
1.向前移动一米(+1)
2.向后移动一米(-1)
3.移动到2*n(移动到二倍农夫当前米数)
牛不动
求农夫走到牛所在位置的最短时间(分钟)并输出。

ac代码
#include<iostream>
#include<queue>
using namespace std;
const int maxn=1e5+5;
int n,k;
bool vis[maxn];
int ans;
struct p{
	int x,s;
}v,u,nn;
inline bool pp(int x){
	return x>=0&&x<=100000&&!vis[x];
};
queue<p> q;
void bfs(){
	while(!q.empty()){
		u=q.front();
		q.pop();
		if(u.x==k){
			ans=u.s;
			return;
		}
		//int xx,ss;
		for(int i=1;i<=3;++i){
			if(i==1){
				nn.x=u.x-1;
			}
			else if(i==2){
				nn.x=u.x+1;
			}
			else nn.x=u.x*2;
			if(pp(nn.x)){
				nn.s=u.s+1;
				vis[nn.x]=1;
				q.push(nn);
			}
		}
		
	}
}
int main(){
	scanf("%d %d",&n,&k);
	v.x=n,v.s=0;
	vis[n]=1;
	q.push(v);
	bfs();
	printf("%d\n",ans);
}

Lake Counting

题意:有一块N×M的土地,雨后积起了水,有水标记为‘W’,干燥为‘.’。八连通的积水被认为是连接在一起的。请求出院子里共有多少水洼?

输入:第一行为N,M(1≤N,M≤110)。

下面为N * M的土地示意图。

输出:一行,共有的水洼数。

ac代码
#nclude<iostream>
#include<queue>
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
using pii = pair<int, int>;
const int inf = 0x3f3f3f3f;
const int maxn = 1e5 + 5;
const int dir[8][2] = { {-1,0},{0,-1},{1,0},{0,1} ,{-1,-1},{-1,1},{1,-1},{1,1}};
int n,m;
char a[1000][1000];
int sum;
queue<pii>q;
void bfs(int x,int y){
	a[x][y]='.';
	q.push({x,y});
	while(!q.empty()){
		int xt=q.front().first;
		int yt=q.front().second;
		q.pop();
		for(int i=0;i<8;i++){
			int w=xt+dir[i][0];
			int e=yt+dir[i][1];
			if(w>0&&w<=n&&e>0&&e<=m&&a[w][e]=='W'){
				a[w][e]='.';
				q.push({w,e});
			}
			
		}
	}
	
}
int main() {
	ios;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>a[i][j];
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(a[i][j]=='W'){
			
				bfs(i,j);
				sum++;
			}		
		}
	}
	cout<<sum<<endl;
	return 0;
}

迷宫问题

题意

定义一个二维数组:

int maze[5][5] = {

	0, 1, 0, 0, 0,

	0, 1, 0, 1, 0,

	0, 0, 0, 0, 0,

	0, 1, 1, 1, 0,

	0, 0, 0, 1, 0,

};

它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。

输入
一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。
输出
左上角到右下角的最短路径,格式如样例所示。

反向输出

ac代码
#include<iostream>
#include<queue>
using namespace std;
int map[10][10];
int dx[5]={0,0,1,-1};
int dy[5]={1,-1,0,0};
int vis[10][10];
struct node{
	int x,y;
}pr[10][10];
bool pa(int x,int y){
	return x<5&&x>=0&&y>=0&&y<5&&!vis[x][y]&&!map[x][y];
}
void bfs(){
	queue<node> q;
	node p;
	p.x=0;
	p.y=0;
	q.push(p);
	vis[0][0]=1;
	while(!q.empty()){
		node pp=q.front();
		if(pp.x==4&&pp.y==4){
			return ;
		}
		q.pop();
		for(int i=0;i<4;++i){
			p.x=pp.x+dx[i];
			p.y=pp.y+dy[i];
			if(pa(p.x,p.y)){
				vis[p.x][p.y]=1;
				q.push(p);
				pr[p.x][p.y]=pp;
			}
		}
	}
}
void print(int x,int y){
	if(x==0&&y==0){
		printf("(%d, %d)\n",x,y);
		return;
	}
	print(pr[x][y].x,pr[x][y].y);
	printf("(%d, %d)\n",x,y);
	return ;
}
int main(){
	for(int i=0;i<5;++i){
		for(int j=0;j<5;++j){
			scanf("%d",&map[i][j]);
		}
	}
	bfs();
	print(4,4);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值