ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

营救 题解

2021-08-05 14:03:18  阅读:236  来源: 互联网

标签:队列 int 题解 bfs vis 哥伦比亚号 1005 营救


经典的bfs题,有详解

申明:有不同的意见可以评论或私信我。

题目:营救

铁塔尼号遇险了!他发出了求救信号。距离最近的哥伦比亚号收到了讯息,时间就是生命,必须尽快赶到那里。

通过侦测,哥伦比亚号获取了一张海洋图。这张图将海洋部分分化成 n*n 个比较小的单位,其中用 1 标明的是陆地,用 0 标明是海洋。船只能从一个 0 格子,移到相邻的四个格子中的一个 0 格子。

为了尽快赶到出事地点,哥伦比亚号最少需要走多远的距离。

输入

第一行为 n。

下面是一个 n*n 的 0、1 矩阵,表示海洋地图, n<=1000

最后一行为四个小于 n 的整数,分别表示哥伦比亚号铁塔尼号的位置。

输出

哥伦比亚号到铁塔尼号的最短距离。


样例输入

3
001
101
100
1 1 3 3

样例输出

4


步骤详解

那么像这种有坐标的题目,首先要搞坐标结构体,尤其是 bfs。

struct Node{
	int x,y;
};

对于方向,最基本的 direction 定量也要写好。

const int dx[4]={0,0,1,-1};
const int dy[4]={1,-1,0,0};

当然因为有结构体也可以搞点花里胡哨的。(不过我觉得更麻烦了不是么)

const Node dir[4]={{1,0},{-1,0},{0,1},{0,-1}};

接着就是其他的变量

int n;
int pgx,pgy/*哥伦比亚号坐标*/;
int ptx,pty/*铁塔尼号坐标*/;
int vis[1005][1005]/*查重和步数*/;
int mp[1005][1005]/*地图*/;
queue<Node> q;//队列 

其中 vis 很重要!!!

这里还给大家推荐一个妙招(不是)

bool in(int x,int y){
    return 1<=x&&x<=n&&1<=y&&y<=n;      
}

但是不知道大家有没有注意到啊,输入是没有空格的。
所以我们的输入程序要这么写:

cin>>n;
for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)
		scanf("%1d",&mp[i][j]);
cin>>pgx>>pgy>>ptx>>pty;

由于我们的vis不仅要查重,还要计算步数,故我们拿 -1 和 0 来查重0 及以上拿来算步数

memset(vis,-1,sizeof vis);

我直接把bfs用int返回值用void当然也可以玩,所以输出可以这样写:

cout<<bfs(pgx,pgy);

那我们可以开始看核心 bfs 怎么写了。
首先要清楚 bfs 的模板

void bfs(/*起始点*/) {
	/*将起始点放入队列中*/; 
	/*标记起点访问*/;
	while(/*如果队列不为空*/) { 
		/*访问队列中队首元素*/;
		/*删除队首元素*/;
		for(/*x 所有相邻点*/) {
			if(/*判断条件,不越界&&不阻拦&&未走过*/) {
				/*将该点加入队列末尾*/;
				/*标记该点已访问*/; 
			} 
		} 
	}
	/*队列为空,广搜结束*/; 
} 

那现在这题的 bfs 变成了这样:

int bfs(int a,int b){//起始点坐标 
	q.push({a,b});//将起始点放入队列 
	vis[a][b]=0;//标记 
	while(!q.empty()){//如果队列不为空 
		Node xy=q.front();//访问队首元素 
		q.pop();//删除队首元素 
		for(int i=0;i<4;i++){//所有相邻点 
			int xx=xy.x+dx[i],yy=xy.y+dy[i];//相邻点坐标 
			if(in(xx,yy)&&!mp[xx][yy]&&vis[xx][yy]==-1){//判断条件,不越界&&不阻拦&&未走过
				q.push({xx,yy});//加入队列末尾 
				vis[xx][yy]=vis[xy.x][xy.y]+1;//标记已访问,顺便标记步数 
			}
		}
	}
	return vis[ptx][pty];//最后的标记即总步数 
}

下面是所有代码

#include<bits/stdc++.h>
using namespace std;
struct Node{
	int x,y;
};//坐标结构体 
const int dx[4]={0,0,1,-1};
const int dy[4]={1,-1,0,0};/*方向*/
int n,pgx,pgy/*哥伦比亚号坐标*/,ptx,pty/*铁塔尼号坐标*/;
int vis[1005][1005]/*查重和步数*/
bool mp[1005][1005]/*地图*/;
queue<Node> q;//队列 
bool in(int x,int y){
    return 1<=x&&x<=n&&1<=y&&y<=n;      
}//范围判断函数 
int bfs(int a,int b){//起始点坐标 
	q.push({a,b});//将起始点放入队列 
	vis[a][b]=0;//标记 
	while(!q.empty()){//如果队列不为空 
		Node xy=q.front();//访问队首元素 
		q.pop();//删除队首元素 
		for(int i=0;i<4;i++){//所有相邻点 
			int xx=xy.x+dx[i],yy=xy.y+dy[i];//相邻点坐标 
			if(in(xx,yy)&&!mp[xx][yy]&&vis[xx][yy]==-1){//判断条件,不越界&&不阻拦&&未走过
				q.push({xx,yy});//加入队列末尾 
				vis[xx][yy]=vis[xy.x][xy.y]+1;//标记已访问,顺便标记步数 
			}
		}
	}
	return vis[ptx][pty];//最后的标记即总步数 
}
int main(){
	cin>>n;
	memset(vis,-1,sizeof vis); 
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			scanf("%1d",&mp[i][j]);//注意输入,没有空格 
	cin>>pgx>>pgy>>ptx>>pty;
	cout<<bfs(pgx,pgy); 
	return 0;
}

完结撒花✿✿ヽ(°▽°)ノ✿

标签:队列,int,题解,bfs,vis,哥伦比亚号,1005,营救
来源: https://www.cnblogs.com/joshuahxz210/p/15102970.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有