算法设计期末考试(七天冲刺)

目录

Day 1——图的搜索算法

深度优先搜索(DFS)

小岛问题四向递归

小岛问题八向递归

广度优先搜索(BFS)

小岛问题四向递归

 小岛问题八向递归


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

本博客资料、代码来源于清华大学出版社算法设计与分析,本博客仅用于个人学习,可能存在纰漏,敬请批评指正。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值