目录
Day 1——图的搜索算法
深度优先搜索(DFS)
小岛问题四向递归
给你一个由 '1'
(陆地)和 '0'
(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
示例 1:
输入:grid = [ ["1","1","1","1","0"], ["1","1","0","1","0"], ["1","1","0","0","0"], ["0","0","0","0","0"] ] 输出:1
可以观察出,本问题的小岛是从“1”开始,上下左右(四向)连接的众多“1”的集合。
输入:grid = [ ["1","1","0","0","0"], ["1","1","0","0","0"], ["0","0","1","0","0"], ["0","0","0","1","1"] ] 输出:3
而该实例有三个岛屿,因为红色陆地在四向上没有和绿色、黄色陆地直接的连接。
#include <bits/stdc++.h>
using namespace std;
char tu[11][11];//初始化一个11行11列的图
int a[101];//用来存放不同岛屿面积的数组
int x[5]={0,0,1,0,-1};//四向递归
int y[5]={0,1,0,-1,0};
int n,m;//岛屿的行列数
其中int x[5]={0,0,1,0,-1},int y[5]={0,1,0,-1,0};
x代表x轴的方向
y代表y轴的方向
两两上下组合就代表递归时移动的方向——上下左右
void dfs(int xx,int yy)
{
int i,j;
int ydx,ydy;//ydx在x轴上移动
tu[xx][yy]='.';
for(i=1;i<=4;i++)
{
ydx=xx+x[i];//在x,y轴往四个方向移动{(0,1)//上,(0,-1)//下,(-1,0)//左,(1,0)//右}
ydy=yy+y[i];
if(ydx>=0&&ydx<=n-1&&ydy>=0&&ydy<=m-1&&
tu[ydx][ydy]=='#')//移动不超过图的边界并且移动的方向是岛屿
{
dfs(ydx,ydy);
}
}
return;
}
#include <bits/stdc++.h>
using namespace std;
char tu[11][11];
int a[101];
int x[5]={0,0,1,0,-1};
int y[5]={0,1,0,-1,0};
int n,m;
void dfs(int xx,int yy)
{
int i,j;
int ydx,ydy;
tu[xx][yy]='.';
for(i=1;i<=4;i++)
{
ydx=xx+x[i];
ydy=yy+y[i];
if(ydx>=0&&ydx<=n-1&&ydy>=0&&ydy<=m-1&&
tu[ydx][ydy]=='#')
{
dfs(ydx,ydy);
}
}
return;
}
int main()
{
int i,j,k=0,s=0;
scanf("%d%d",&n,&m);/输入小岛几行几列
for(i=0;i<=n-1;i++)
//gets(tu[i]);
scanf("%s",tu[i]);//输入岛屿
for(i=0;i<=n-1;i++)
for(j=0;j<=m-1;j++)
{
if(tu[i][j]=='#')//如果遍历到陆地,从它开始找到一片完整的岛屿
{
s+=1;//岛屿数量
dfs(i,j);
}
}
printf("%d",s);
return 0;
}
输入:
7 7
.......
.##....
.##....
..#.##.
...#.#.
...###.
.##....
输出:3
小岛问题八向递归
递归的八个方向
int x[9]={0,0,1,0,-1,1,1,-1,-1};
int y[9]={0,1,0,-1,0,1,-1,1,-1};
for(i=1;i<=8;i++)
{
ydx=xx+x[i];//在x,y轴组成的八个坐标方向移动
ydy=yy+y[i];
if(ydx>=0&&ydx<=n-1&&ydy>=0&&ydy<=m-1&&
tu[ydx][ydy]=='#')
{
dfs(ydx,ydy);
}
}
#include <bits/stdc++.h>
using namespace std;
char tu[11][11];
int a[101];
int x[9]={0,0,1,0,-1,1,1,-1,-1};
int y[9]={0,1,0,-1,0,1,-1,1,-1};
int n,m,area=0;
void dfs(int xx,int yy)
{
int i,j;
int ydx,ydy;
tu[xx][yy]='.';
area+=1;//每次递归都代表新找到一片连接的陆地,每次递归岛屿面积都要加一
for(i=1;i<=8;i++)
{
ydx=xx+x[i];
ydy=yy+y[i];
if(ydx>=0&&ydx<=n-1&&ydy>=0&&ydy<=m-1&&
tu[ydx][ydy]=='#')
{
dfs(ydx,ydy);
}
}
return;
}
int main()
{
int i,j,k=0,s=0;
scanf("%d%d",&n,&m);
for(i=0;i<=n-1;i++)
//gets(tu[i]);
scanf("%s",tu[i]);
for(i=0;i<=n-1;i++)
for(j=0;j<=m-1;j++)
{
if(tu[i][j]=='#')
{
s+=1;//岛屿个数
dfs(i,j);
a[k]=area;//不同岛屿的面积
area=0;
k++;
}
}
printf("%d\n",s);
sort(a,a+k);//快速排序,从小到大k个不同岛屿
printf("%d\n",a[k-1]);//最大岛屿
for(int i=0;i<k;i++)
printf("%d ",a[i]);//所有岛屿的面积
return 0;
}
输入:
7 7
.......
.##....
.##....
..#.##.
....##.
....##.
..#....
输出:
3//岛屿个数
6//最大岛屿的面积
1 5 6//岛屿面积
广度优先搜索(BFS)
小岛问题四向递归
#include <bits/stdc++.h>
using namespace std;
char tu[11][11];
int a[105];
int x[5]={0,0,1,0,-1};
int y[5]={0,1,0,-1,0};
int dui[105][2];// 二维数组dui用于存储BFS过程中的位置,每个元素是一个坐标对。
int n,m;
void bfs(int xx,int yy)
{
int i,j;
int t=0,w=1;//变量t和w分别跟踪当前搜索层和未访问的节点数量。
int ydx,ydy;
tu[xx][yy]='.';//如果是联通的,则标记为访问过
dui[t][0]=xx;
dui[t][1]=yy;
do{
for(i=1;i<=4;i++)
{
ydx=dui[t][0]+x[i];
ydy=dui[t][1]+y[i];
if(ydx>=0&&ydx<=n-1&&ydy>=0&&ydy<=m-1
&&tu[ydx][ydy]=='#')
{
dui[w][0]=ydx;//w是从队列中取出新节点进行访问的计数
dui[w][1]=ydy;
tu[ydx][ydy]='.';
w++;//当遍历完当前层的节点后,会更新 t 的值为 w 的值
}
}
t++;//当所有可能的位置都被访问后,增加搜索层数t,然后继续下一层搜索,直到所有可达位置都被访问。
}while(t<w);
return;
}
int main()
{
int i,j,k=0,s=0;
int gs=0;
scanf("%d%d",&n,&m);
for(i=0;i<=n-1;i++)
//gets(tu[i]);
scanf("%s",tu[i]);
for(i=0;i<=n-1;i++)
for(j=0;j<=m-1;j++)
{
if(tu[i][j]=='#')
{
s+=1;
bfs(i,j);
}
}
printf("%d",s);
return 0;
}
输入:
7 7
.......
.##....
.##....
..#.##.
.....#.
...###.
.##....
输出:3
小岛问题八向递归
#include <bits/stdc++.h>
using namespace std;
char tu[11][11];
int a[105];
int x[9]={0,0,1,0,-1,1,1,-1,-1};
int y[9]={0,1,0,-1,0,1,-1,1,-1};
int dui[105][2];
int n,m;
void bfs(int xx,int yy)
{
int i,j;
int t=0,w=1;//头 尾
int ydx,ydy;
tu[xx][yy]='.';
dui[t][0]=xx;
dui[t][1]=yy;
do{
for(i=1;i<=8;i++)
{
ydx=dui[t][0]+x[i];
ydy=dui[t][1]+y[i];
if(ydx>=0&&ydx<=n-1&&ydy>=0&&ydy<=m-1
&&tu[ydx][ydy]=='#')
{
dui[w][0]=ydx;
dui[w][1]=ydy;
tu[ydx][ydy]='.';
w++;
}
}
t++;
}while(t<w);
return;
}
int main()
{
int i,j,k=0,s=0;
int gs=0;
scanf("%d%d",&n,&m);
for(i=0;i<=n-1;i++)
//gets(tu[i]);
scanf("%s",tu[i]);
for(i=0;i<=n-1;i++)
for(j=0;j<=m-1;j++)
{
if(tu[i][j]=='#')
{
s+=1;
bfs(i,j);
}
}
printf("%d",s);
return 0;
}
输入:
7 7
.......
.##....
.##....
..#.##.
.....#.
...###.
.##....
输出:2
本博客资料、代码来源于清华大学出版社算法设计与分析,本博客仅用于个人学习,可能存在纰漏,敬请批评指正。