【数学】100332. 包含所有 1 的最小矩形面积 II

本文涉及知识点

数学

LeetCode100332. 包含所有 1 的最小矩形面积 II

给你一个二维 二进制 数组 grid。你需要找到 3 个 不重叠、面积 非零 、边在水平方向和竖直方向上的矩形,并且满足 grid 中所有的 1 都在这些矩形的内部。
返回这些矩形面积之和的 最小 可能值。
注意,这些矩形可以相接。
示例 1:
输入: grid = [[1,0,1],[1,1,1]]
在这里插入图片描述

输出: 5
解释:
位于 (0, 0) 和 (1, 0) 的 1 被一个面积为 2 的矩形覆盖。
位于 (0, 2) 和 (1, 2) 的 1 被一个面积为 2 的矩形覆盖。
位于 (1, 1) 的 1 被一个面积为 1 的矩形覆盖。
示例 2:

输入: grid = [[1,0,1,0],[0,1,0,1]]
输出: 5
在这里插入图片描述

解释:
位于 (0, 0) 和 (0, 2) 的 1 被一个面积为 3 的矩形覆盖。
位于 (1, 1) 的 1 被一个面积为 1 的矩形覆盖。
位于 (1, 3) 的 1 被一个面积为 1 的矩形覆盖。

提示:
1 <= grid.length, grid[i].length <= 30
grid[i][j] 是 0 或 1。
输入保证 grid 中至少有三个 1 。

数学

我们假设某个最优解,包括左上1 的为rect1,包括右下1的矩形为rect2,另外一个矩形为rect3。我们将整个网格水平、竖直划分成3$\times$3 共9块。
第一块是:左上角是(0,0),右下角是rect1的右下角。
第二块是:左上角是rect2的左上角,右下角是网格右下角。
rect3可能站4块,也可能占3块,也可能占2块,也可能占一块。占4块包括所有占2块,占2块包括所有占1块。
下图的红色并是各种可能。
在这里插入图片描述
我们将其转化为网格的大矩形中寻找包括所有1的最小矩形。大矩形分四种情况:
在这里插入图片描述
四种情况:
一,三竖。
二,三横。
三,一竖二横。
四,一横二竖。
rect2 四种情况全部是3格,rect1 前两种情况是三格,后两种情况是二格。
遗漏了两种情况
在这里插入图片描述
借用别人的总结:
在这里插入图片描述

预处理

各矩形包括全部1的最小矩形的面积,如果不包括1,返回1000。

旧代码

需要枚举4个坐标,非常容易出错。代码通过不了,只能通过部分样例。继续调试时间成本太高。

class Solution {
public:int minimumSum(vector<vector<int>>& grid) {m_r = grid.size();m_c = grid[0].size();memset(m_area, 1, sizeof(m_area));for (int r1 = 0; r1 < m_r; r1++) {for (int c1 = 0; c1 < m_c; c1++) {for (int r2 = r1; r2 < m_r; r2++) {for (int c2 = c1; c2 < m_c; c2++) {Init(grid, r1, r2, c1, c2);}}}}for (int r1 = 0; r1 < m_r; r1++) {for (int c1 = 0; c1 < m_c; c1++) {if (0 == grid[r1][c1]) { continue; }for (int r2 = r1 + 1; r2 < m_r; r2++) {for (int c2 = 0; c2 < m_c; c2++) {Do(r1, r2, c1, c2);}}for (int c2 = c1 + 1; c2 < m_c; c2++) {for (int r2 = 0; r2 < m_r; r2++) {Do(r1, r2, c1, c2);}}}}return m_ans;}void Do( int r1, int r2, int c1, int c2) {//三横m_ans = min(m_ans, Area(0,r1,0,m_c - 1) + Area(r1 + 1,r2 - 1,0,m_c - 1) + Area(r2,m_r - 1,0,m_c - 1));//三竖m_ans = min(m_ans, Area(0,m_r - 1,0,c1) + Area(0, m_r - 1, c1 + 1,c2 - 1) + Area(0, m_r - 1, c2,m_c - 1));//一长度2的横,二长度3的竖m_ans = min(m_ans, Area(0,r1,0,c2 - 1) + Area(r1 + 1,c2 - 1,0,c2 - 1) + Area(0,m_r - 1,c2,m_c - 1));//一长度为2的竖,二长度为3横m_ans = min(m_ans, Area(0,r2 - 1,0,c1) + Area(0,r2 - 1,c1 + 1,m_c - 1) + Area(r2,m_r - 1,0,m_c - 1));//一长度3的横,二长度2的竖m_ans = min(m_ans, Area(0, r1, 0, m_c - 1) + Area(r1 + 1, c2 - 1, 0, c2 - 1) + Area(r1+1, m_r - 1, c2, m_c - 1));//一长度为3的竖,二长度为2横m_ans = min(m_ans, Area(0, m_r - 1, 0, c1) + Area(0, r2 - 1, c1 + 1, m_c - 1) + Area(r2, m_r - 1, c1+1, m_c - 1));}int Area(int r1, int r2, int c1, int c2) {if ((r1 < 0) || (r1 >= m_r)) { return m_iNotMay; }if ((r2 < 0) || (r2 >= m_r)) { return m_iNotMay; }if ((c1 < 0) || (c2 >= m_c)) { return m_iNotMay; }if ((c2 < 0) || (c2 >= m_c)) { return m_iNotMay; }return m_area[r1][r2][c1][c2];}void Init(const vector<vector<int>>& grid,int r1,int r2,int c1,int c2) {int right = -1, bottom = -1, left = 2000, top = 2000;for (int r = r1; r <= r2; r++) {for (int c = c1; c <=c2; c++) {if (grid[r][c]) {right = max(right, c);bottom = max(bottom, r);left = min(left, c);top = min(top, r);}}}m_area[r1][r2][c1][c2] = (right - left + 1) * (bottom - top + 1);}const int m_iNotMay = 1000'000;int m_area[30][30][30][30];int m_r, m_c;int m_ans = 1000'000;
};

新代码

六种情况,只需要枚举两个变量。如果用预处理,时间复杂度O(nm)或O(nn)或O(mm)。
不用预处理时间复杂度:O(nmnn)也能过,故不用预处理。

class Solution {
public:int minimumSum(vector<vector<int>>& grid) {m_r = grid.size();m_c = grid[0].size();auto Area =[&]( int r1, int r2, int c1, int c2) {int right = -1, bottom = -1, left = 2000, top = 2000;for (int r = r1; r <= r2; r++) {for (int c = c1; c <= c2; c++) {if (grid[r][c]) {right = max(right, c);bottom = max(bottom, r);left = min(left, c);top = min(top, r);}}}return (right - left + 1) * (bottom - top + 1);};{//三横for (int r1 = 0; r1 < m_r; r1++) {for (int r2 = r1 + 2; r2 < m_r; r2++) {m_ans = min(m_ans, Area(0,r1,0,m_c-1)+Area(r1+1,r2-1,0,m_c-1) + Area(r2,m_r-1,0,m_c-1));}}}{//三竖for (int c1 = 0; c1 < m_c; c1++) {for (int c2 = c1 + 2; c2 < m_c; c2++) {m_ans = min(m_ans, Area(0, m_r-1, 0,c1) + Area(0, m_r - 1, c1+1,c2-1) + Area(0, m_r - 1, c2,m_c-1));}}}for (int r = 0; r + 1 < m_r; r++) {for (int c = 0; c + 1 < m_c; c++) {//上一下二m_ans = min(m_ans, Area(0, r, 0, m_c - 1) + Area(r + 1,m_r - 1, 0, c) + Area(r + 1, m_r - 1, c+1, m_c - 1));//上二下一m_ans = min(m_ans, Area(0, r, 0, c) + Area(0, r, c+1, m_c-1) + Area(r + 1, m_r - 1, 0, m_c - 1));//左一右二m_ans = min(m_ans, Area(0, m_r - 1, 0, c) + Area(0, r, c + 1, m_c - 1) + Area(r+1, m_r - 1, c + 1, m_c - 1));//左二右一m_ans = min(m_ans, Area(0, r, 0, c) + Area(r+1,m_r-1, 0, c) + Area(0, m_r - 1, c + 1, m_c - 1));}}	return m_ans;}	const int m_iNotMay = 1000'000;int m_r, m_c;int m_ans = 1000'000;
};

代码

template<class T1, class T2>
void AssertEx(const T1& t1, const T2& t2)
{Assert::AreEqual(t1, t2);
}template<class T>
void AssertEx(const vector<T>& v1, const vector<T>& v2)
{Assert::AreEqual(v1.size(), v2.size());for (int i = 0; i < v1.size(); i++){Assert::AreEqual(v1[i], v2[i]);}
}template<class T>
void AssertV2(vector<vector<T>> vv1, vector<vector<T>> vv2)
{sort(vv1.begin(), vv1.end());sort(vv2.begin(), vv2.end());Assert::AreEqual(vv1.size(), vv2.size());for (int i = 0; i < vv1.size(); i++){AssertEx(vv1[i], vv2[i]);}
}namespace UnitTest
{vector<vector<int>> grid;TEST_CLASS(UnitTest){public:TEST_METHOD(TestMethod00){grid = { {1,0,1},{1,1,1} };auto res = Solution().minimumSum(grid);AssertEx(5, res);}TEST_METHOD(TestMethod01){grid = { {1,0,1,0},{0,1,0,1} };auto res = Solution().minimumSum(grid);AssertEx(5, res);}TEST_METHOD(TestMethod02){grid = { {0,1},{1,1} };auto res = Solution().minimumSum(grid);AssertEx(3, res);}TEST_METHOD(TestMethod03){grid = { {0,0,0},{0,1,0},{0,1,1},{0,0,0} };auto res = Solution().minimumSum(grid);AssertEx(3, res);}};
}

扩展阅读

视频课程

先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

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

相关推荐

我想对大家说的话
《喜缺全书算法册》以原理、正确性证明、总结为主。
按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

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

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

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

相关文章

vant4的组件气泡弹出框van-popover,在列表中遍历后点击一个全部/显示隐藏,解决办法

环境&#xff1a;vue3 vant-ui4 <div v-for"(info, index) in item.infoListVOs" :key"index"><van-popoverv-model:show"showPopover":actions"actions"overlayplacement"bottom-end"select"onSelect(info…

软件工程全套学习培训资料,实际优质项目编制及各类建设方案,信息安全,运维资料

目的&#xff1a;规范系统开发流程&#xff0c;提高系统开发效率。 立项申请需求分析方案设计方案评审开发调整测试阶段系统培训试运行测试验收投入使用 所有文档过去进主页获取。 获取方式&#xff1a;本文末个人名片直接获取。 软件资料清单列表部分文档清单&#xff1a;工作…

AGI 远不止 ChatGPT!一文入门 AGI 通识及应用开发_通向agi之路网站使用什么开发的网站

AI 大语言模型进入爆发阶段 2022 年 12 月 ChatGPT 突然爆火&#xff0c;原因是其表现出来的智能化已经远远突破了我们的常规认知。虽然其呈现在使用者面前仅仅只是一个简单的对话问答形式&#xff0c;但是它的内容化水平非常强大&#xff0c;甚至在某些方面已经超过人类了&am…

程序的调试技术,设置断点

断点&#xff08;break point&#xff09;是指在代码中指定位置&#xff0c;当程序运行到此位置时变中断下来&#xff0c;并让开发者可查看此时各变量的值。因断点中断的程序并没有结束&#xff0c;可以选择继续执行。 在程序的调试过程中&#xff0c;设置断点是一个很有用的分…

可用的搜索引擎

presearchhttps://presearch.com/yandexhttps://ya.ru

书归正传,说说颍川士族

我的非遗项目是《颍川士族传说》&#xff0c;此前做的视频只是触及了边缘&#xff0c;属于气氛的营造&#xff0c;今后就正式转入主题了。 首先说说什么是士族&#xff0c;它有两个同义词&#xff1a;世族和势族。“世”是一代又一代的意思&#xff0c;“势”是权势&#xff0…

python中类的继承详解

面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力&#xff1a;它可以使用现有类的所有功能&#xff0c;并在无需重新编写原来的类的情况下对这些功能进行扩展 &#xff08;1&#xff09;在类的继承中&#xff0c;存在父类跟子类&#xff0c;子类可以继…

【项目实训】数据库内容丰富

经团队讨论&#xff0c;对前端页面展示数据进行了增加&#xff0c;于是相应的修改数据库 经团队成员使用大模型对各公司面试经验中问题的总结优化&#xff0c;我们打算将大模型的回答存储到数据库中&#xff0c;以显示在前端页面 于是在数据库中存储大模型的回答&#xff1a;…

三种三相交流电动机正反转互锁电路的分析

PLC和固态继电器应用都很普及了&#xff0c;常规电磁继电器还有用武之地吗?答案是&#xff1a;有用武之地的。因为微处理器的应用使逻辑控制发生了变革&#xff0c;极大地发挥了开关功能的特性&#xff0c;但在应用中&#xff0c;它还是无法承受较大的负载&#xff0c;因此还要…

Charles网络抓包工具安装和web抓包(一)

目录 概述 抓包工具对比 安装 下载 web抓包配置 按键说明 前言-与正文无关 ​ 生活远不止眼前的苦劳与奔波&#xff0c;它还充满了无数值得我们去体验和珍惜的美好事物。在这个快节奏的世界中&#xff0c;我们往往容易陷入工作的漩涡&#xff0c;忘记了停下脚步&#…

Unity开发者转UE 新手必读

前言 本页面为熟悉Unity的用户概述了 虚幻引擎(UE)。如果你具备一些Unity知识&#xff0c;而且想学习如何运用自己所学的知识在虚幻引擎中工作&#xff0c;下面各小节将帮助你入门。 下面的截图并排显示了Unity和虚幻编辑器。各个区域采用相同的颜色来表示相同的功能。每个区…

用友 U8+ 控制金额、单价等字段权限设置

进入路径 系统服务——权限——数据权限控制设置 本功能是数据权限设置的前提&#xff0c;用户可以根据需要先在数据权限控制设置中选择需要进行权限控制的对象。 数据权限的控制分为记录级和字段级两个层次&#xff0c;对应系统中的两个页签"记录级"和"字段…

LabVIEW在光学与光子学实验室中的应用

光学与光子学实验室致力于光学和光子学前沿领域的研究&#xff0c;涉及超快光学、非线性光学、光纤通信、光子晶体等多个方向。实验室需要高精度的实验控制和数据采集系统&#xff0c;以进行复杂的光学实验&#xff0c;并对实验数据进行实时处理和分析。 项目需求 实时控制与监…

Vue + SpringBoot 实现文件的断点上传、秒传,存储到Minio

一、前端 1. 计算文件的md5值 前端页面使用的elment-plus的el-upload组件。 <el-upload action"#" :multiple"true" :auto-upload"false" :on-change"handleChange" :show-file-list"false"><FileButton content&…

telnet_h3c_ap

import telnetlib import time # 定义交换机参数 HOSTS [10.61.168.x, ]for HOST in HOSTS:tn telnetlib.Telnet(HOST,timeout22)tn.read_until(b"Password: ")tn.write("h3capadmin".encode(ascii) b"\n") ##h3c默认密码time.sleep(0.2)tn.…

JS对象、数组、字符串超详细方法

JavaScript 对象方法 对象创建的方式 对象字面量 var dog1 {name: "大黄",age: 2,speak: function () {console.log("汪汪");}, };使用Object构造函数 var dog2 new Object(); dog2.name "大黄"; dog2.age 2; dog2.speak function () …

BIO、NIO编程深入理解与直接内存、零拷贝

网路编程基本常识 一. Socket 什么是Socket Socket是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。它提供了应用层进程利用网络协议交换数据的机制&#xff0c;是应用程序与网络协议栈进行交互的接口。 说白了&#xff0c;Socket就是把TCP/IP协议族进行封装…

iOS之如何创建.a静态库

番外&#xff1a;想要查看如何创建.framework静态库可前往看我​​​​​​​iOS之如何创建.framework静态库-CSDN博客这篇文章。 一、创建静态库项目 ①、打开 Xcode 并创建一个新的 Xcode 项目。 ②、选择 "macOS" -> "Framework & Library" -&…

Nginx基础概念和常用操作

文章目录 1. 安装、启动、连接2. 快速尝试部署网站3. 配置文件1. nginx.conf全局配置事件模块HTTP 模块性能优化建议 2. default.confserver 块基本设置日志设置根路径设置 4. 反向代理1. 模拟3个Web2. 链接 5. 负载均衡1. 加权轮询&#xff0c;Weighted Round Robin2. 最少连接…

用Microsoft.Extensions.Hosting 管理WPF项目.

首先引入必要的包: <ItemGroup><PackageReference Include"CommunityToolkit.Mvvm" Version"8.2.2" /><PackageReference Include"Microsoft.Extensions.Hosting" Version"8.0.0" /><PackageReference Include&q…