卡码网 104题 在力扣中为827题 都是一个意思
104. 建造最大岛屿
题目描述
给定一个由 1(陆地)和 0(水)组成的矩阵,你最多可以将矩阵中的一格水变为一块陆地,在执行了此操作之后,矩阵中最大的岛屿面积是多少。
岛屿面积的计算方式为组成岛屿的陆地的总数。岛屿是被水包围,并且通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设矩阵外均被水包围。
输入描述
第一行包含两个整数 N, M,表示矩阵的行数和列数。之后 N 行,每行包含 M 个数字,数字为 1 或者 0,表示岛屿的单元格。
输出描述
输出一个整数,表示最大的岛屿面积。
输入示例
4 5
1 1 0 0 0
1 1 0 0 0
0 0 1 0 0
0 0 0 1 1
输出示例
6
提示信息
对于上面的案例,有两个位置可将 0 变成 1,使得岛屿的面积最大,即 6。
数据范围:
1 <= M, N <= 50。
思路:
两步 1. 先把整个图遍历了 把每个岛屿的面积都记录在哈希表中然后进行标号
2. 再遍历一遍图 然后把0位置的上下左右位置都检测一遍 把岛号都存到哈希表中(这个是为了避免找到相同的岛屿多加了所以用哈希表能唯一性)
遍历完了四个位置 之后直接找哈希表中的岛号 用map中的映射取对应岛的面积 相加岛的面积之后 和最大的岛屿面积做对比 取一个最大的
关于为什么要找最大的岛面积 我估计是因为有每个岛之间都离得很远连不上的情况 然后就只能找最大面积的岛加1 作为最大人工岛
代码:
using System;
class Program
{
//公式化输入
public static int n;
public static int m;
static void Main()
{
string[] inputs=Console.ReadLine().Split();
n=int.Parse(inputs[0]);
m=int.Parse(inputs[1]);
// 声明数组 填充输入数组
int[,] grid=new int [n,m];
for(int i=0;i<n;i++)
{
inputs=Console.ReadLine().Split();
for(int j=0;j<m;j++)
{
grid[i,j]=int.Parse(inputs[j]);
}
}
// 开始正题
int maxArea=0; //不同岛屿的最大面积
int IndexLand=2; //岛号标识索引 从2 开始
//1.对所有的岛屿进行编号并且 记录岛屿的面积
Dictionary<int,int> map=new Dictionary<int,int>(); //新建字典用于存储不同编号的岛的面积是多少
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(grid[i,j]==1)
{
int Area= Dfs(grid,i,j,IndexLand); //求得岛的面积
map[IndexLand]=Area; ///存进字典里 IndexLand是键 Area是值
IndexLand++; //遍历完一个岛了让岛号加加
maxArea=Math.Max(Area,maxArea);//记录面积最大岛的面积 后续要用
}
}
}
//2.对每个0 海洋格子进行遍历 计算他和相邻岛的合并面积
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
//新建一个哈希表 用来储存当前位置遍历的四个位置的岛的编号或者说没岛也行
HashSet<int> set=new HashSet<int>();
if(grid[i,j]==0)
{
//上
if(i-1>=0 && grid[i-1,j]>=2) //如果当前位置在范围内并且 他的索引大于等于2 证明是岛
{
set.Add(grid[i-1,j]);//将岛编号存进哈希表中
}
if(i+1<n && grid[i+1,j]>=2) //下
{
set.Add(grid[i+1,j]);
}
if(j-1>=0&& grid[i,j-1]>=2)//左
{
set.Add(grid[i,j-1]);
}
if(j+1<m && grid[i,j+1]>=2)//右
{
set.Add(grid[i,j+1]);
}
//把当前的0改成1 面积初始值从1开始算
int sumarea=1;
foreach(int area in set) //从set中取岛号
{
sumarea+=map[area];//岛号对应的面积
}
//更新最大面积
maxArea=Math.Max(sumarea,maxArea);
}
}
}
Console.WriteLine(maxArea);
}
public static int Dfs(int[,] grid ,int r,int c,int IndexLand )
{
if(r<0 ||r >=n ||c<0||c>=m)
{
return 0;
}
if(grid[r,c]!=1) //如果遍历到的下一个值小于pre也就是当前值 那么证明没法走通这个格子直接返回
{
return 0;
}
grid[r,c]=IndexLand;
return 1+ Dfs(grid,r,c+1,IndexLand)
+Dfs(grid,r,c-1,IndexLand)
+Dfs(grid,r+1,c,IndexLand)
+Dfs(grid,r-1,c,IndexLand);
}
}