【分类讨论】【割点】1568. 使陆地分离的最少天数

作者推荐

动态规划的时间复杂度优化

本文涉及知识点

分类讨论 割点

LeetCode1568. 使陆地分离的最少天数

给你一个大小为 m x n ,由若干 0 和 1 组成的二维网格 grid ,其中 1 表示陆地, 0 表示水。岛屿 由水平方向或竖直方向上相邻的 1 (陆地)连接形成。
如果 恰好只有一座岛屿 ,则认为陆地是 连通的 ;否则,陆地就是 分离的 。
一天内,可以将 任何单个 陆地单元(1)更改为水单元(0)。
返回使陆地分离的最少天数。
示例 1:
输入:grid = [[0,1,1,0],[0,1,1,0],[0,0,0,0]]
在这里插入图片描述

输出:2
解释:至少需要 2 天才能得到分离的陆地。
将陆地 grid[1][1] 和 grid[0][2] 更改为水,得到两个分离的岛屿。
示例 2:
在这里插入图片描述

输入:grid = [[1,1]]
输出:2
解释:如果网格中都是水,也认为是分离的 ([[1,1]] -> [[0,0]]),0 岛屿。
提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 30
grid[i][j] 为 0 或 1

分类讨论

岛屿数只要不为1都是分离的陆地。
岛屿数 = 连通区域 - 水单元数。
一个岛屿只有一块陆地或两块陆地,无法分割,只能花一天或两天变成0岛屿。
3块陆地的岛屿只需要一天就可以分割。由于是4连接,无法两两相连。
4块陆地的岛屿一定可以两天分离,右上的那块陆地 右边和上边没有连接,最坏的情况把左下的两块陆地消掉,右上的陆地和余下的陆地就成了两个岛屿。

如何查看岛屿数量是否为1

并集查找后,看各陆地的是否是同一连通区域。

如果计算能否一天搞定

枚举各陆地,删除后看能否符合题意。

大致思路

一,岛屿数量是否为1,如果不是返回0.
二,枚举各陆地,删除,如果岛屿数量不为1,返回1。
三,返回2。

割点

一,岛屿数量是否为1,如果不是返回0.
二,如果只有1块或2块陆地,直接陆地数量。
三,如果存在割点,返回1。
四,返回2。

代码

核心代码

class CEnumGridEdge
{
public:void Init(){for (int r = 0; r < m_r; r++){for (int c = 0; c < m_c; c++){Move(r, c, r + 1, c);Move(r, c, r - 1, c);Move(r, c, r, c + 1);Move(r, c, r, c - 1);}}}const int m_r, m_c;
protected:CEnumGridEdge(int r, int c) :m_r(r), m_c(c){}void Move(int preR, int preC, int r, int c){if ((r < 0) || (r >= m_r)){return;}if ((c < 0) || (c >= m_c)){return;}OnEnumEdge(preR, preC, r, c);};virtual void OnEnumEdge(int preR, int preC, int r, int c) = 0;
};
//割点
class CCutPoint
{
public:CCutPoint(const vector<vector<int>>& vNeiB) : m_iSize(vNeiB.size()){m_vTime.assign(m_iSize, -1);m_vVisitMin.assign(m_iSize, -1);for (int i = 0; i < m_iSize; i++){if (-1 != m_vTime[i]){continue;}m_iRegionCount++;dfs(i, -1, vNeiB);}}int RegionCount()const{return m_iRegionCount;}vector<int> CutPoints()const{return m_vCutPoints;}
protected:void dfs(int cur, int parent, const vector<vector<int>>& vNeiB){auto& curTime = m_vTime[cur];auto& visitMin = m_vVisitMin[cur];curTime = m_iTime++;visitMin = curTime;int iMax = -1;int iChildNum = 0;for (const auto& next : vNeiB[cur]){if (next == parent){continue;}if (-1 != m_vTime[next]){visitMin = min(visitMin, m_vTime[next]);continue;}iChildNum++;dfs(next, cur, vNeiB);visitMin = min(visitMin, m_vVisitMin[next]);iMax = max(iMax, m_vVisitMin[next]);}if (-1 == parent){if (iChildNum >= 2){m_vCutPoints.emplace_back(cur);}}else{if (iMax >= curTime){m_vCutPoints.emplace_back(cur);}}}vector<int> m_vTime;//各节点到达时间,从0开始。 -1表示未处理vector<int> m_vVisitMin;// int m_iTime = 0;int m_iRegionCount = 0;vector<int> m_vCutPoints;const int m_iSize;
};class CNeiBo : public CEnumGridEdge
{
public:CNeiBo(const vector<vector<int>>& grid, int r, int c):CEnumGridEdge(r,c), m_iMaskCount(r*c), m_grid(grid){m_vNeiBo.resize(m_iMaskCount);Init();}// 通过 CEnumGridEdge 继承virtual void OnEnumEdge(int preR, int preC, int r, int c) override{if (m_grid[preR][preC] && m_grid[r][c]){const int iMask = m_c * r + c;const int iPre = m_c * preR + preC;m_vNeiBo[iPre].emplace_back(iMask);}}const int m_iMaskCount;vector<vector<int>> m_vNeiBo;const vector<vector<int>>& m_grid;
};
class Solution {
public:int minDays(vector<vector<int>>& grid) {CNeiBo neiBo(grid, grid.size(), grid[0].size());CCutPoint cut(neiBo.m_vNeiBo);int iZeroCount = 0;for (const auto& v : grid){iZeroCount += std::count(v.begin(), v.end(), 0);}if (1 != cut.RegionCount()- iZeroCount){return 0;}if (neiBo.m_iMaskCount - iZeroCount <= 2){return neiBo.m_iMaskCount - iZeroCount;}if (cut.CutPoints().size()){return 1;}return 2;}
};

测试用例


template<class T,class T2>
void Assert(const T& t1, const T2& t2)
{assert(t1 == t2);
}template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{if (v1.size() != v2.size()){assert(false);return;}for (int i = 0; i < v1.size(); i++){Assert(v1[i], v2[i]);}}int main()
{vector<vector<int>> grid;{Solution sln;grid = { {0,1,1,0},{0,1,1,0},{0,0,0,0} };auto res = sln.minDays(grid);Assert(2, res);}{Solution sln;grid = { {0},{0} };auto res = sln.minDays(grid);Assert(0, res);}{Solution sln;grid = { {1},{1} ,{1} };auto res = sln.minDays(grid);Assert(1, res);}{Solution sln;grid = { {1},{1} };auto res = sln.minDays(grid);Assert(2, res);}{Solution sln;grid = { {1} };auto res = sln.minDays(grid);Assert(1, res);}}

2023年4月版

class Solution {
public:
int minDays(vector<vector>& grid) {
m_r = grid.size();
m_c = grid[0].size();
int iTotal = 0;
for (int r = 0; r < m_r; r++)
{
for (int c = 0; c < m_c; c++)
{
if (1 == grid[r][c])
{
iTotal++;
}
}
}
if (iTotal < 2)
{
return iTotal;
}
if (iTotal != AnyAUnionNum(grid))
{
return 0;
}
for (int r = 0; r < m_r; r++)
{
for (int c = 0; c < m_c; c++)
{
if (0 == grid[r][c])
{
continue;
}
grid[r][c] = 0;
if (iTotal != 1+AnyAUnionNum(grid))
{
return 1;
}
grid[r][c] = 1;
}
}
return 2;
}
int AnyAUnionNum(const vector<vector>& grid)
{
int iNum = 0;
for (int r = 0; r < m_r;r++ )
{
for (int c = 0; c < m_c; c++ )
{
if (1 == grid[r][c])
{
return NeiBNum(r, c, grid);
}
}
}
return 0;
}
int NeiBNum(int iR, int iC, const vector<vector>& grid)
{
std::unordered_set setRC;
queue<pair<int, int>> que;
setRC.emplace(iR*100+iC);
que.emplace(iR, iC);
while (que.size())
{
const auto it = que.front();
que.pop();
auto Add = [&](int r,int c)
{
if ((r < 0) || (r >= m_r))
{
return;
}
if ((c < 0) || (c >= m_c))
{
return;
}
if (1 != grid[r][c])
{
return;
}
int iRCMask = 100 * r + c;
if (setRC.count(iRCMask))
{
return;
}
setRC.emplace(iRCMask);
que.emplace(r, c);
};
Add(it.first + 1, it.second);
Add(it.first - 1, it.second);
Add(it.first, it.second + 1);
Add(it.first, it.second - 1);
}
return setRC.size();
}
int m_r, m_c;
vector<vector> m_vNeiNum;
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/504326.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

wayland(xdg_wm_base) + egl + opengles 使用 Assimp 加载3D model 最简实例(十三)

文章目录 前言一、3D model 文件介绍1. 3d model 介绍1.1 如何获取3d model 文件1.2 3d model 的文件格式1.3 obj模型数据格式2. 3d 立方体 model 实例——cube.obj二、Assimp 介绍1. Assimp 简介2.ubuntu 上安装libassimp3. 使用Assimp 解析 cube.obj 文件3.1 assimp_load_cub…

舟山群岛 “垃圾不落海”的“她力量”

2月28日下午&#xff0c;天气阴雨绵绵&#xff0c;浙江省舟山市岱山县长涂岛沿港边的一间平房内&#xff0c;渔嫂杨淑雯、杨淑清、庄亚芬正在认真梳理从渔船上、渔港街巷捡回来的一大堆饮料瓶。 分类、装袋、打包&#xff0c;记者发现&#xff0c;这间不大的仓库内&#xff0c…

JavaScript练手小技巧:一文看懂<script>标签的 ansyc 和 defer

<script>标签的 ansyc 和 defer 属性。只对外部加载 JS 文件有效。 <script src"js/app.js" async></script> <script src"js/app.js" defer></script> 普通加载 js&#xff08;同步加载&#xff09;&#xff1a;会打断 …

NCDA设计大赛获奖作品剖析:UI设计如何脱颖而出?

第十二届大赛简介 - 未来设计师全国高校数字艺术设计大赛&#xff08;NCDA&#xff09;开始啦&#xff01;视觉传达设计命题之一: ui 设计&#xff0c;你想知道的都在这里。为了让大家更好的参加这次比赛&#xff0c;本文特别为大家整理了以往NCDA大赛 UI 设计的优秀获奖作品&a…

STM32标准库——(14)I2C通信协议、MPU6050简介

1.I2C通信 I2C 通讯协议(Inter&#xff0d;Integrated Circuit)是由Phiilps公司开发的&#xff0c;由于它引脚少&#xff0c;硬件实现简单&#xff0c;可扩展性强&#xff0c; 不需要USART、CAN等通讯协议的外部收发设备&#xff0c;现在被广泛地使用在系统内多个集成电路(IC)间…

利用IP地址识别风险用户:保护网络安全的重要手段

随着互联网的发展和普及&#xff0c;网络安全问题日益突出&#xff0c;各种网络诈骗、恶意攻击等风险不断涌现&#xff0c;给个人和企业的财产安全和信息安全带来了严重威胁。在这样的背景下&#xff0c;利用IP地址识别风险用户成为了保护网络安全的重要手段之一。IP数据云探讨…

Pytest插件pytest-selenium-让自动化测试更简洁

在现代Web应用的开发中&#xff0c;自动化测试成为确保网站质量的重要手段之一。而Pytest插件 pytest-selenium 则为开发者提供了简单而强大的工具&#xff0c;以便于使用Python进行Web应用的自动化测试。本文将深入介绍 pytest-selenium 插件的基本用法和实际案例&#xff0c;…

搜索算法(算法竞赛、蓝桥杯)--DFS迭代加深

1、B站视频链接&#xff1a;B25 迭代加深 Addition Chains_哔哩哔哩_bilibili 题目链接&#xff1a;Addition Chains - 洛谷 #include <bits/stdc.h> using namespace std; int n,d;//d为搜索的深度 int a[10005];//存储加成的序列bool dfs(int u){//搜索第u层 if(ud)r…

QT实现机器视觉图片查看窗口

QT实现机器视觉常用图像查看器 在机器视觉行业中最常见的控件就是图像查看器了&#xff0c;使用QT实现其实也非常简单&#xff0c;在我出的项目【降龙&#xff1a;算法软件框架】和【重明&#xff1a;工业相机二次开发】中都有用到。可以说只要你要开发一个和机器视觉相关的软…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的钢材表面缺陷检测系统(Python+PySide6界面+训练代码)

摘要&#xff1a;开发钢材表面缺陷检测系统对于保障制造质量和提高生产效率具有关键作用。本篇博客详细介绍了如何运用深度学习构建一个钢材表面缺陷检测系统&#xff0c;并提供了完整的实现代码。该系统基于强大的YOLOv8算法&#xff0c;并对比了YOLOv7、YOLOv6、YOLOv5&#…

ABAP - SALV教程 01- 开篇:打开SALV的三种方式之一

关于SALV&#xff0c;这里参考巨佬江正军的文章讲解&#xff0c;在做SAP开发的遇到困难和瓶颈的时候&#xff0c;每每读到巨佬的文章都会灵感爆发、醍醐灌顶。https://www.cnblogs.com/jiangzhengjun/p/4291387.html 博主由于是由JAVA转型的ABAP开发&#xff0c;刚接触ABAP的时…

Android和Linux的嵌入式开发差异

最近开始投入Android的怀抱。说来惭愧&#xff0c;08年就听说这东西&#xff0c;当时也有同事投入去看&#xff0c;因为恶心Java&#xff0c;始终对这玩意无感&#xff0c;没想到现在不会这个嵌入式都快要没法搞了。为了不中年失业&#xff0c;所以只能回过头又来学。 首先还是…