【分類討論】【割點】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.pswp.cn/news/714480.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/714480.shtml
英文地址,請注明出處:http://en.pswp.cn/news/714480.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

接口詳細說明

接口概述 接口也是一種規范 接口的定義與特點 接口的格式如下&#xff1a; //接口用關鍵字interface來定義 public interface 接口名 {// 常量// 抽象方法 } JDK8之前接口中只能是抽象方法和常量&#xff0c;沒有其他成分了。 接口不能實例化。 接口中的成員都是public修…

webpack打包一個文件,做了哪些事情

用webpack打包一個文件&#xff0c;在webpack內部做了哪些事情&#xff0c;用代碼詳細介紹一下 當你使用 Webpack 打包一個文件時&#xff0c;Webpack 內部會進行一系列操作來實現模塊加載、代碼轉換、依賴分析、模塊打包等功能。以下是使用 Webpack 打包一個簡單 JavaScript …

svn介紹 4.0

一、svn介紹&#xff08;版本控制工具&#xff09; 1、svn的定義&#xff1a; svn是一個開放源代碼的版本控制系統&#xff0c;通過采用分支管理系統的高效管理&#xff0c;簡而言之就是用于多個人共同開發同一個項目&#xff0c;實現共享資源&#xff0c;實現最終集中式個管…

電腦數據丟失是什么原因 易我數據恢復軟件下載 easyrecovery數據恢復軟件下載 電腦數據刪除了怎么恢復 電腦數據庫損壞了怎么找回

目錄 一、電腦數據丟失是什么原因 二、電腦數據丟失如何恢復 三、EasyRecovery恢復電腦數據的方法介紹 電腦是我們大家熟悉并且常用的數據存儲設備&#xff0c;也是綜合性非常強的數據處理設備。對于電腦設備來講&#xff0c;最主要的數據存儲介質是硬盤&#xff0c;電腦硬…

CMU15445實驗總結(Spring 2023)

CMU15445實驗總結(Spring 2023) 背景 菜鳥博主是2024屆畢業生&#xff0c;學歷背景太差&#xff0c;導致23年秋招無果&#xff0c;準備奮戰春招。此前有讀過LevelDB源碼的經歷&#xff0c;對數據庫的了解也僅限于LevelDB。奔著”有對比才能學的深“的理念&#xff0c;以及緩解…

linux系統Jenkins工具配置webhook自動部署

Jenkins工具webhook自動部署 webhook自動部署webhook的意義操作流程jenkins頁面操作gitlab頁面操作 webhook自動部署 webhook的意義 自動化部署&#xff1a;Webhook 可以在代碼提交、合并請求或其他特定事件發生時自動觸發 Jenkins 構建和部署任務&#xff0c;從而實現自動化…

C#,K中心問題(K-centers Problem)的算法與源代碼

1 K中心問題&#xff08;K-centers Problem&#xff09; k-centers problem: 尋找k個半徑越小越好的center以覆蓋所有的點。 比如&#xff1a;給定n個城市和每對城市之間的距離&#xff0c;選擇k個城市放置倉庫&#xff08;或ATM或云服務器&#xff09;&#xff0c;以使城市…

【JavaEE進階】 Spring AOP源碼簡單剖析

文章目錄 &#x1f343;前言&#x1f340;Spring AOP源碼剖析?總結 &#x1f343;前言 前面的博客中&#xff0c;博主對代理模式進行了一個簡單的講解&#xff0c;接下來博主將對Spring AOP源碼進行簡單剖析&#xff0c;使我們對Spring AOP了解的更加深刻。 &#x1f340;Sp…

leetcode 簡單

1. 兩數之和 兩數之和 方法1&#xff1a;暴力枚舉 兩次for 循環&#xff0c;記錄索引和值&#xff0c;找到合適的值然后返回 方法2&#xff1a;使用哈希表 第一次for循環的時候&#xff0c;就可以使用哈希表記錄key的value&#xff0c;可以實現時間復雜度是1&#xff0c;要分…

【前端素材】推薦優質后臺管理系統網頁Highdmin平臺模板(附源碼)

一、需求分析 1、系統定義 后臺管理系統是一種用于管理和控制網站、應用程序或系統的管理界面。它通常被設計用來讓網站或應用程序的管理員或運營人員管理內容、用戶、數據以及其他相關功能。后臺管理系統是一種用于管理網站、應用程序或系統的工具&#xff0c;通常由管理員使…

express+mysql+vue,從零搭建一個商城管理系統7--文件上傳,大文件分片上傳

提示&#xff1a;學習express&#xff0c;搭建管理系統 文章目錄 前言一、安裝multer&#xff0c;fs-extra二、新建config/upload.js三、新建routes/upload.js四、修改routes下的index.js五、修改index.js六、新建上傳文件test.html七、開啟jwt驗證token&#xff0c;通過login接…

Vue.js+SpringBoot開發開放實驗室管理系統

目錄 一、摘要1.1 項目介紹1.2 項目錄屏 二、研究內容2.1 實驗室類型模塊2.2 實驗室模塊2.3 實驗管理模塊2.4 實驗設備模塊2.5 實驗訂單模塊 三、系統設計3.1 用例設計3.2 數據庫設計 四、系統展示五、樣例代碼5.1 查詢實驗室設備5.2 實驗放號5.3 實驗預定 六、免責說明 一、摘…

vue3的router

需求 路由組件一般放在&#xff0c;pages或views文件夾, 一般組件通常放在component文件夾 路由的2中寫法 子路由 其實就是在News組件里面&#xff0c;再定義一個router-view組件 他的子組件&#xff0c;機會渲染在router-view區域 路由傳參 <RouterLink :to"/news…

解決導入項目后在idea中不顯示的問題

問題&#xff1a; 今天下午重新打開寒假之前負責的項目&#xff0c;發現打不開了&#xff0c; 從master拉取最新代碼到我的分支&#xff0c;發現我的分支上顯示就是這樣子&#xff0c;無論怎么更新代碼都不行。 原因&#xff1a; 在上一次上傳代碼的時候&#xff0c;我把我分…

leetcode括號生成

題目描述 解題思路 首先看到題目&#xff0c;一開始是并沒有思路的。這時候可以在紙上進行演算一下結果。當只有一對括號的時候&#xff0c;我們可以得知結果[“()”],當有兩對括號的時候&#xff0c;我們可以發現&#xff0c;括號在第一個基礎上&#xff0c;要么在括號內部出…

靜態時序分析:SDC約束命令set_case_analysis詳解

相關閱讀 靜態時序分析https://blog.csdn.net/weixin_45791458/category_12567571.html?spm1001.2014.3001.5482 目錄 指定值 指定端口/引腳列表 簡單使用 set_case_analysis命令用于對電路進行特定模式的設定&#xff0c;例如對于一個工作在正常模式下的芯片&#xff0c;…

HTML5新特性:為Web帶來的翻天覆地變化

隨著互聯網的發展&#xff0c;HTML5作為Web開發的重要里程碑&#xff0c;為我們帶來了一系列令人興奮的新特性和功能。本文將帶領大家探索HTML5的新特性&#xff0c;揭示其對Web技術的巨大影響。 一、介紹 HTML5作為HTML的最新版本&#xff0c;不僅強化了網頁結構與內容&#…

Android 解決引入的三方庫中類名沖突問題

參考&#xff1a; Android開發——如何解決三方庫中的類名沖突問題_android 類沖突-CSDN博客 Android 解決 jar/aar 包類名沖突 - 簡書 實操步驟 1.提前安裝好unzip-5.51-bin&#xff0c;proguard-7.4.0&#xff0c;jarjar-1.4軟件 2.解壓包名沖突的 AAR 文件 進入到需要修…

reach功能的使用

1.reach添加后 1.reach添加后2 2.拷貝reach最后一幀的動作 3.刪除reach(注意畫選時如果reach延長不能直接刪否則以前的動畫也會刪掉&#xff0c;要縮短reach后再刪另外這兩個灰原點也要刪掉否則影響后邊新加clip的對齊會出現亂七八糟的事情) 4.刪除reach后&#xff0c;光標移到…

收藏:數據防泄漏系統推薦,數據防泄漏系統有哪些?

一金融機構在近期發生了一起數據泄露事件。 經過調查&#xff0c;發現是由于一名員工將包含客戶敏感信息的文件通過電子郵件發送給了未經授權的第三方。 這一事件導致客戶數據泄露&#xff0c;給該機構帶來了嚴重的聲譽損失和信任危機。 這一案例凸顯了數據防泄漏系統的重要性…