【LeetCode-204】1568. 使陆地分离的最少天数

【困难】1568. 使陆地分离的最少天数

思路:

注意:

  1. 判断连通块数量cnt是否大于1/等于0
    遍历每个结点,如果某个点未被遍历且为1,则找到了一个连通块,此时需要使用dfs判断周围是否有相连陆地(为了将此块陆地所连接的所有1进行标记)
  2. 如果(cnt > 1 || cnt == 0),不需要操作,直接返回0
    否则,再次遍历,依次尝试删除一块陆地能否满足cnt>1,如果能满足,则返回1;否则返回2(默认一定有解)
  • 只需要将陆地分开,每个陆地可以是一个1,也可以是多个1连在一起形成一个连通分量
    所以将陆地分离,就是找到大于等于两个的连通分量,即连通分块数量>1
  • 找到第一个1,将其隔离,答案一定为0,1,2

代码:

class Solution 
{
public:
    int n,m;    //数组的长宽
    vector<vector<bool>> st;    //状态数组
    vector<vector<int>> g;
    int dx[4]={-1,0,1,0}, dy[4]={0,1,0,-1};

    void dfs(int x, int y)  //2.遍历
    {
        st[x][y]=true;
        for(int i=0;i<4;i++)
        {
            int a=x+dx[i], b=y+dy[i];     //遍历四个方向的点,使用偏移量dx,dy
            if(a>=0 && a<n && b>=0 && b<m && !st[a][b] && g[a][b]==1)   //未越界 且 未遍历 且 为1
                dfs(a,b);
        }      
    }

    bool check()    //1.判断连通块数量是否大于1/等于0
    {
        int cnt=0;  //连通块的数量
        st = vector<vector<bool>>(n,vector<bool>(m));//将状态数组清空
        for(int i=0;i<n;i++)//枚举所有是1的点
            for(int j=0;j<m;j++)
                if(!st[i][j] && g[i][j]==1)
                {
                    cnt++;
                    dfs(i,j);
                }

        return (cnt>1 || cnt==0);
    }

    int minDays(vector<vector<int>>& grid) 
    {
        n=grid.size(), m=grid[0].size();
        g=grid;

        if(check()) return 0;   //有大于1个的连通块 不用操作 输出0
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
                if(g[i][j])
                {
                    g[i][j]=0;
                    if(check()) return 1;   //删除一个陆地后进行判断 如果cnt>1 执行一步;否则恢复现场
                    g[i][j]=1;
                } 

        return 2;   //默认一定有解 最多2步
    }
};

相关链接:

  1. vector
st = vector<vector<bool>>(n,vector<bool>(m));//将状态数组清空
vector<vector<bool>> st;    //状态数组
  1. LeetCode题目汇总
  2. 可以将此题看作图论中的无向图,类似有线电视网络题
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值