BFS 广(宽)度优先搜索题目推荐以及题解(1)

        嗯哼!数月未出现的学生党蒟蒻,出关了。虽说放暑假已经有一些时日了,呃呃呃,但没关系,家人们别介意,最近在洛谷做了一些题,找到了一些比较适合像本蒟蒻一样的新手刷一下的广搜,也就是BFS。好,话不多说,上强度。

        1.P1683 入门

        先放个题目,方便家人们阅读,嘻嘻嘻。

        af849672de214a80ac78de451e06276e.png

        首先读题,很容易发现,这就是一道赤裸裸的广搜。

        接着看样例和数据范围(必须看,尤为重要)

0b37e9920fa64fdf9fd76c9ac2f0f7aa.png

        一看这输入样例,搜索落实了。而且有实力的家人们一定发现了,这就是妥妥的连通性问题,其实是比较水的,至于这个文章的描述,呃呃呃,人家语文水平好,甘拜下风。

        分析:

        其次,和平时的广度优先搜索的套路一样,先开一个char类型的mp[23][23]的数组,代表地图,其次用vis[23][23]表示该点是否搜索过,再定义dx[],dy[],表示上下左右的点,该题本蒟蒻用的是上右下左,在代码中也注释了,再用STL的queue的队列逐个搜索,直到得到答案。要注意的是,这道题中的队列是一直搜索到没有路为止的。

        或许会有家人们质疑,真的这么简单?实不相瞒,这只是一道很普通的普及-

        好,由于这题比较简单,本蒟蒻就直接上代码了,希望家人们遵循洛谷的规则,阿里嘎多。

        代码如下:

#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
char mp[23][23];
bool vis[23][23];
int dx[4]={-1,0,1,0};      //上右下左
int dy[4]={0,1,0,-1};      //上右下左
int w,h,x,y,ans=1;
struct node{
	int x,y;
};
bool check(int x,int y){
	if((mp[x-1][y]=='#'||vis[x-1][y])&&
		(mp[x][y-1]=='#'||vis[x][y-1])&&
		(mp[x+1][y]=='#'||vis[x+1][y])&&
		(mp[x][y+1]=='#'||vis[x][y+1])) 
		return true;
	else return false;
}
void bfs(int x,int y){
	queue<node> q;
	node Front;
	Front.x=x;Front.y=y;
	q.push(Front);
	while(!q.empty()){
		node fron=q.front();
		q.pop();
		if(check(fron.x,fron.y)){
			continue;
		}
		for(int i=0;i<4;i++){
			node now;
			now.x=fron.x+dx[i];
			now.y=fron.y+dy[i];
			if(mp[now.x][now.y]=='#'||vis[now.x][now.y]) continue;
			q.push(now);
			vis[now.x][now.y]=true;
			ans++;
		}
	}
}
int main(){
	for(int i=0;i<23;i++){
		for(int j=0;j<23;j++){
			vis[i][j]=true;
		}
	}
	cin>>w>>h;
	for(int i=1;i<=h;i++){
		for(int j=1;j<=w;j++){
			cin>>mp[i][j];
			vis[i][j]=false;
			if(mp[i][j]=='@'){
				x=i;
				y=j;
			}
		}
	}
	vis[x][y]=true;
	bfs(x,y);
	cout<<ans;
	return 0;
}

        接着就可以直接AC了。好,趁热打铁,接着下一道。

        2.P1747 好奇怪的游戏

        照常,上题目:

cfa4fa1a9a0d47c9b1286998dd4fc343.png

        这是一道普及/提高-,但其实本蒟蒻觉得难度还是一样,看来下一篇还得上点强度才行,嘻嘻嘻。

        读题,这这这,居然有马走日也能走田的游戏!?难评,逆天。

        接下来是输入输出样例和数据范围:

c02fbdc8aa8b468f8a215787ef356db6.png        分析:

        两匹马,黑马,白马。呃呃呃,家人们,管他黑马白马,能解出题的就是好代码!!!   

        其实,基本思路都是差不多的,我们只需要将dx[],dy[]数组的数据改一改,也就是下一步的数据改一下,有点繁琐,但管他呢,还是那句“能解出题的就是好代码”(狗头)(狗头)。

        每一步一共可以扩展12个点,如下:

                dx[12]={-2,-1,1,2,2,1,-1,-2,-2,2,2,-2};
                dy[12]={-1,-2,-2,-1,1,2,2,1,-2,-2,2,2};

        不一定要按照我的顺序,但一定要相匹配,不然就WA了。

        另外,定义的结构体node中,要加上个step,记录下白马或黑马从(1,1)到该节点的步数。每拓展一个节点就+1,注意不是+7。

        而两匹马要分别广搜,不用担心时间复杂度,因为根本剪不了枝,至少本蒟蒻不行。或许有家人觉得距离目标节点越来越远的节点不用搜索,但实则不然,因为会有一些特殊情况,必须先走离目标节点较远的田,再走日才能到达。

        但家人们不用担心,时间复杂度完全够用,因为x,y都小于20。

        好,上代码:

#include<iostream>
#include<queue>
using namespace std;
int x1,y1,x2,y2;
int dx[12]={-2,-1,1,2,2,1,-1,-2,-2,2,2,-2};
int dy[12]={-1,-2,-2,-1,1,2,2,1,-2,-2,2,2};
bool vis[1010][1010];
struct node{
	int x,y,step=0;
};
int bfs(int x,int y){
	for(int i=0;i<1010;i++){
		for(int j=0;j<1010;j++){
			vis[i][j]=false;
		}
	}
	queue<node> q;
	node fron;
	fron.x=x;fron.y=y;
	q.push(fron);
	while(!q.empty()){
		fron=q.front();
		q.pop();
		for(int i=0;i<12;i++){
			node now;
			now.x=fron.x+dx[i];
			now.y=fron.y+dy[i];
			if(vis[now.x][now.y]||now.x<1||now.y<1)continue;
			now.step=fron.step+1;   
			q.push(now);
			vis[now.x][now.y]=true;
			if(now.x==1&&now.y==1){
				return now.step;
			}
//			cout<<now.x<<" "<<now.y<<" "<<now.step<<endl;
		}
//		cout<<endl;
	}
}
int main(){
	cin>>x1>>y1>>x2>>y2;
	cout<<bfs(x1,y1)<<endl<<bfs(x2,y2);
	return 0;
}

        细节的家人们会发现有两行注释了,那是本蒟蒻当时调试时写的,自己动手写的家人们也可以参考一下我是怎么调试的。

        以上是洛谷中的两道关于BFS的题目,贪多嚼不烂,今天就先讲着两题,这两题比较适合练速度,加深理解的,初学者也可以先从这两题开始入手,一开始可能会写个把来小时,但这是正常现象,这种还是得多练的,但毕竟也不太难。

        本蒟蒻要下了,家人们,如果有问题可以随时提出,谢谢家人们的鼓励与支持。

 

(侵删)

 

 

  • 27
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值