宽度优先搜索(BFS)算法之一——最短路径
2.1 马的遍历 P1443
有一个 的棋盘,在某个点 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。
输入数据格式
输入只有一行四个整数,分别为 。
输出数据格式
一个 的矩阵,代表马到达某个点最少要走几步(不能到达则输出 )。
输入输出样例
输入 #1 | 输出 #1 |
---|---|
3 3 1 1 | 0 3 2 3 -1 1 2 1 4 |
说明与提示
数据规模与约定
对于全部的测试点,保证 ,。
参考代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
int vis[405][405]; //方格
struct Tnode{ //队列
int x,y;
} qu[405*405];
int dx[8]={-1,-2,-2,-1,1,2,2,1};
int dy[8]={2,1,-1,-2,2,1,-1,-2};//8个方向
void bfs(int x0, int y0) {
int head=0,tail=0; //队列的头和尾
qu[0].x = x0; //开始位置进队列
qu[0].y = y0;
tail++;
vis[x0][y0]=0; //记录到x,y的步数,同时也充当探索标记(=-1 表示没有探索过)
int ans=0;
while (head<tail){//队列非空
int x = qu[head].x; //取队列的头
int y = qu[head].y;
head++; //出队列
int step = vis[x][y]; //父节点到x,y所需要的步数
for (int d=0; d<8; d++) {
int nx=x+dx[d]; //四周坐标
int ny=y+dy[d];
if (nx>=1 && nx<=n && ny>=1 && ny<=m && vis[nx][ny]==-1){ //可以进入
vis[nx][ny]=step+1;
qu[tail].x = nx; //进队列
qu[tail++].y = ny;
}
}
}
return;
}
int main(){
int x,y;
cin >> n >> m >> x>>y;
//for(int i=1;i<=n;i++)
// for(int j=1;j<=m;j++)
// vis[i][j]=-1;
memset(vis,0xff,sizeof(vis));
bfs(x,y);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)
cout<<vis[i][j]<<" ";
cout<<"\n";
}
return 0;
}
2.2 离开中山路 P1746
爱与愁大神买完东西后,打算坐车离开中山路。现在爱与愁大神在 处,车站在 处。现在给出一个 的地图, 表示马路, 表示店铺(不能从店铺穿过),爱与愁大神只能垂直或水平着在马路上行进。爱与愁大神为了节省时间,他要求最短到达目的地距离(每两个相邻坐标间距离为 )。你能帮他解决吗?
输入数据格式
第 行包含一个数 。
第 行到第 行:整个地图描述( 表示马路, 表示店铺,注意两个数之间没有空格)。
第 行:四个数 。
输出数据格式
只有 行,即最短到达目的地距离。
输入输出样例
输入 #1 | 输出 #1 |
---|---|
3 001 101 100 1 1 3 3 | 4 |
说明与提示
对于 数据,满足 。
对于 数据,满足 。
参考代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
string vis[1005]; //方格
int step[1000][1000];
struct Tnode{ //队列
int x,y;
} qu[1000005];
int dx[4]={-1,0,+1,0};
int dy[4]={0,+1,0,-1};//4个方向
void bfs(int x0, int y0) {
int head=0,tail=0; //队列的头和尾
qu[0].x = x0; //开始位置进队列
qu[0].y = y0;
tail++;
vis[x0][y0]=0; //记录到x,y的步数,同时也充当探索标记(=-1 表示没有探索过)
int ans=0;
while (head<tail){//队列非空
int x = qu[head].x; //取队列的头
int y = qu[head].y;
head++; //出队列
for (int d=0; d<4; d++) {
int nx=x+dx[d]; //四周坐标
int ny=y+dy[d];
if (nx>=0 && nx<n && ny>=0 && ny<n&&vis[nx][ny]=='0'){ //可以进入
vis[nx][ny]='2';
step[nx][ny]=step[x][y]+1;
cout<<nx<<"-"<<ny<<endl;
qu[tail].x = nx; //进队列
qu[tail++].y = ny;
}
}
}
return;
}
int main(){
cin>>n;
for(int i=0;i<n;i++)
cin>>vis[i];
//memset(vis,0xff,sizeof(vis));
int x,y,x2,y2;
cin >> x >> y >> x2>>y2;
bfs(x-1,y-1);
cout<<step[x2-1][y2-1];
return 0;
}
2.3 岛屿的最大面积
给定一个由 0 和 1 组成的n*m矩阵 ,用来表示海洋岛屿地图。一个 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直方向上相邻。你可以假设 矩阵的四个边缘都被 0(代表水)包围着。
找到给定的二维数组中最大的岛屿面积。如果没有岛屿,则返回面积为 0 。
例如:
输出的结果是:
6
输入格式
第一行2个正整数n和m,范围[4,1000]。 下面 n行每个行 m个数,都是0或1。
输出格式
1个整数,答案。
输入/输出例子1
输入:
3 3
0 0 1
1 1 0
1 1 1
输出:
5
参考代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[1002][1002]; //方格
int ans=0;
struct Tnode{ //队列
int x,y;
} qu[1000000];
int dx[4] = { 0, 1, 0,-1}; //四个方向
int dy[4] = {-1, 0, 1, 0};
void BFS(int x0, int y0) {
qu[0].x = x0; //开始位置进队列
qu[0].y = y0;
a[x0][y0]=0;
int head=0; //队列的头和尾
int tail=1;
while (head<tail){//队列非空
int x = qu[head].x; //取队列的头
int y = qu[head].y;
head++; //出队列
for (int d=0; d<4; d++) {
int nx=x+dx[d]; //四周坐标
int ny=y+dy[d];
if (a[nx][ny]==1){ //可以
qu[tail].x = nx; //进队列
qu[tail++].y = ny;
a[nx][ny]=0; //访问过标记
}
}
}
if (tail>ans)
ans=tail;
}
int main(){
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]==1)
BFS(i,j);
cout << ans;
return 0;
}