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

news2024/11/16 6:03:29

作者推荐

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

本文涉及知识点

分类讨论 割点

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.coloradmin.cn/o/1483765.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Bootstrap的使用

目录 js的引入&#xff1a; 1.行内式 2.嵌入式 3.外链式 Bootstrap:的引入 注意事项&#xff1a; 条件注释语句&#xff1a; 栅格系统&#xff1a; 列嵌套&#xff1a; 列偏移&#xff1a; 列排序&#xff1a; 响应式工具&#xff1a; Bootstrap的字体图标的使用&a…

【MATLAB源码-第147期】基于matlab的QPSK调制解调在AWGN信道,瑞利信道,莱斯信道理论与实际误码率对比仿真。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 四相位移键控&#xff08;QPSK&#xff0c;Quadrature Phase Shift Keying&#xff09;是一种重要的数字调制技术&#xff0c;它通过改变信号的相位来传输数据。与其他调制技术相比&#xff0c;QPSK在相同的带宽条件下能够传…

某象滑块js逆向(主要是声明拿过我代码的进来)

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;不提供完整代码&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01;wx a15018…

MySQL中json类型的字段

有些很复杂的信息&#xff0c;我们一般会用扩展字段传一个json串&#xff0c;字段一般用text类型存在数据库。mysql5.7以后支持json类型的字段&#xff0c;还可以进行sql查询与修改json内的某个字段的能力。 1.json字段定义 ip_info json DEFAULT NULL COMMENT ip信息, 2.按…

python脚本实现全景站点矩阵转欧拉角

效果 脚本 import re import numpy as np import math import csv from settings import * # 以下是一个示例代码,可以输入3*3旋转矩阵,然后输出旋转角度:# ,输入3*3旋转矩阵# 计算x,y,z旋转角def rotation_matrix_to_euler_angles(R):

缓存相关问题:雪崩、穿透、预热、更新、降级的深度解析

✨✨祝屏幕前的小伙伴们每天都有好运相伴左右✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; 目录 引言 1. 缓存雪崩 1.1 问题描述 1.2 解决方案 1.2.1 加锁防止并发重建缓存 2. 缓存穿透 2.1 问题描述 2.2 解决方案 2.2.1 …

nginx介绍及编译安装

nginx介绍 是一个流行的开源的高性能的HTTP和反向代理服务器&#xff0c;也可以用作邮件代理服务器。它以其高性能、稳定性、丰富的功能集和低资源消耗而闻名 nginx特点 高性能&#xff1a; Nginx以其高效的事件驱动架构而闻名&#xff0c;能够处理大量并发连接而不会消耗过多…

判断点是否在多边形内

std::vector<cv::Point2d> vanCorner_;bool inArea(const Pose &pos) {cv::Point2d point cv::Point2d(pos.position.x(), pos.position.y());double distance cv::pointPolygonTest(vanCorner_, point, false);return distance > 0; } 似乎效果不太好,会误报 …

【BUUCTF web】通关 2.0

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏 …

像用Excel一样用Python:pandasGUI

文章目录 启动数据导入绘图 启动 众所周知&#xff0c;pandas是Python中著名的数据挖掘模块&#xff0c;以处理表格数据著称&#xff0c;并且具备一定的可视化能力。而pandasGUI则为pandas打造了一个友好的交互窗口&#xff0c;有了这个&#xff0c;就可以像使用Excel一样使用…

关于网络安全从硬件防火墙防御到软件防御论述

服务器的硬防和软防是指对服务器进行保护和防御的两个层次。硬防主要是通过物理手段来保护服务器的安全&#xff0c;包括服务器的物理安全和硬件设备的安全。软防则是通过软件和配置来保护服务器的安全&#xff0c;包括操作系统的安全配置、网络安全配置、防火墙、入侵检测系统…

04-Linux实用操作

各种小技巧&#xff08;快捷键&#xff09; 强制停止 Ctrlc强制停止 Linux某些程序的运行&#xff0c;如果想要强制停止它&#xff0c;可以使用快捷键ctrlc 命令输入错误&#xff0c;也可以通过快捷键ctrlc&#xff0c;退出当前输入&#xff0c;重新输入 退出、登出 Ctrld退…

运用qsort函数进行快排并使用C语言模拟qsort

qsort 函数的使用 首先qsort函数是使用快速排序算法来进行排序的&#xff0c;下面我们打开官网来查看qsort是如何使用的。 这里有四个参数&#xff0c;首先base 是至待排序的数组的首元素的地址&#xff0c;num 是值这个数组的元素个数&#xff0c;size 是指每个元素的大小&am…

MySQL进阶之(三)InnoDB数据存储结构之数据页结构

三、InnoDB数据存储结构之数据页结构 3.1 数据库的存储结构3.1.1 MySQL 数据存储目录3.1.2 页的引入3.1.3 页的概述3.1.4 页的上层结构 3.2 数据页结构3.2.1 文件头和文件尾01、File Header&#xff08;文件头部&#xff09;02、File Trailer&#xff08;文件尾部&#xff09; …

麒麟银河操作系统V10部署ffmpeg(也能用于Linux系统)

麒麟银河操作系统V10部署ffmpeg(也能用于Linux系统) 部署ffmpeg用来处理视频的各种操作 想使用ffmpeg&#xff0c;要先安装nasm&#xff0c;yasm&#xff0c;x264之后&#xff0c;否则会报错 nkvers 查看麒麟操作系统版本 cat /proc/version #查看linux版本信息 uname -a …

C++:菱形继承问题

目录 1、什么是菱形继承 2、虚拟继承 3、一些常见问题 1. 什么是菱形继承&#xff1f;菱形继承的问题是什么&#xff1f; 2. 什么是菱形虚拟继承&#xff1f;如何解决数据冗余和二义性的 3. 继承和组合的区别&#xff1f;什么时候用继承&#xff1f;什么时候用组合&#…

模拟栈(数组实现)

题目描述&#xff1a; 代码模板&#xff1a; //push插入操作 void push(int x) {//让栈顶元素从0开始stk[ tt] x; }//pop弹出操作 void pop() {//直接把这个元素跳过&#xff08;相当于弹出&#xff09;tt--; }//empty判断是否为空操作 bool empty() {if(tt > 0) return …

程序员是如何看待“祖传代码”的?

目录 ​编辑 程序员是如何看待“祖传代码”的&#xff1f; 一、什么是“祖传代码”&#xff1f; 二、“祖传代码”的利弊 1. 可以节省开发成本 2. 可能引入安全隐患 3. 可能增加系统的维护难度 三、祖传代对程序员的影响 1. 丰富程序员的技能和知识 2. 提高程序员的创…

在两台CentOS 7服务器上部署MinIO集群---准确

环境说明&#xff1a; 2台Centos7服务器 IP地址分别为172.16.1.9和172.16.1.10 1. 创建minio用户和目录 在两台服务器上执行以下命令&#xff1a; sudo useradd -m -d /app/minio minio sudo mkdir -p /app/minioData sudo mkdir -p /app/minio/logs sudo chown -R mini…

范伟:你们怎么老提1,200呢,有什么典故啊?赵本山:没有啊!

范伟&#xff1a;你们怎么老提1,200呢,有什么典故啊?赵本山&#xff1a;没有啊&#xff01; --小品《面子》&#xff08;中3&#xff09;的台词 表演者&#xff1a;赵本山 高秀敏 范伟 &#xff08;接上&#xff09; 范伟&#xff1a;哎吃啊 赵&#xff1a;哎呀这电视看的挺…