建设最大岛屿/最大人工岛/填海造陆问题 Dfs

卡码网  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);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值