Leetcode 1691. 堆叠长方体的最大高度 [Java/C++] 排序+动态规划(附详细证明过程)

news2024/11/20 9:43:00
给你 n 个长方体 cuboids ,其中第 i 个长方体的长宽高表示为 cuboids[i] = [widthi, lengthi, heighti](下标从 0 开始)。请你从 cuboids 选出一个 子集 ,并将它们堆叠起来。

如果 widthi <= widthj 且 lengthi <= lengthj 且 heighti <= heightj ,你就可以将长方体 i 堆叠在长方体 j 上。你可以通过旋转把长方体的长宽高重新排列,以将它放在另一个长方体上。

返回 堆叠长方体 cuboids 可以得到的 最大高度 。

 

示例 1:

输入:cuboids = [[50,45,20],[95,37,53],[45,23,12]]
输出:190
解释:
第 1 个长方体放在底部,53x37 的一面朝下,高度为 95 。
第 0 个长方体放在中间,45x20 的一面朝下,高度为 50 。
第 2 个长方体放在上面,23x12 的一面朝下,高度为 45 。
总高度是 95 + 50 + 45 = 190 。

示例 2:

输入:cuboids = [[38,25,45],[76,35,3]]
输出:76
解释:
无法将任何长方体放在另一个上面。
选择第 1 个长方体然后旋转它,使 35x3 的一面朝下,其高度为 76 。

示例 3:

输入:cuboids = [[7,11,17],[7,17,11],[11,7,17],[11,17,7],[17,7,11],[17,11,7]]
输出:102
解释:
重新排列长方体后,可以看到所有长方体的尺寸都相同。
你可以把 11x7 的一面朝下,这样它们的高度就是 17 。
堆叠长方体的最大高度为 6 * 17 = 102 。

 

提示:

    n == cuboids.length
    1 <= n <= 100
    1 <= widthi, lengthi, heighti <= 100

解法一:排序 + 动态规划

首先,若我们枚举所有可能的长方体堆叠的排列组合,便可以很简单的寻找出一个高度和最大的答案。从这个思想出发,我们去观察每一个排列。


在这里插入图片描述不失一般性,我们将第一行的数构造为 a 1 ≤ b 1 ≤ c 1 a_1 \le b_1 \le c_1 a1b1c1(通过移动不同的列)

我们从第二列开始构造我们新的堆叠方式:

a1 b1 c1
a2 b2 c2

c 2 c_2 c2小于 a 2 a_2 a2或者 b 2 b_2 b2,那么必然能够利用 a 2 a_2 a2 b 2 b_2 b2中的最大值进行替换使得 c 2 c_2 c2的位置的数变成最大,同理对于 a 2 , b 2 a_2,b_2 a2,b2,我们也能够使得 b 2 b_2 b2是第二大的值(中位数)。我们便能够将第二行转化为: a 2 ≤ b 2 ≤ c 2 a_2 \le b_2 \le c_2 a2b2c2, 通过移动第2-第n行的列,构造得到的新堆叠方式也是合法的。我们从第一列开始进行不断的移动,直至所有的3元组 ( a i , b i , c i ) (a_i,b_i,c_i) (ai,bi,ci)满足 a i ≤ b i ≤ c i a_i \le b_i \le c_i aibici


在这里插入图片描述
我们可以发现,由于我们将最大的值作为高度,那么通过转化后,最终的结果必然优于以前的排列产生的结果。我们可以对所有有效的堆叠方式进行排列,那么每个长方体的情况转化为(长,宽,高) = (最小值,中位数,最大值)。至此,问题转化为:对于给定n个长方体(长,宽,高),其中长<=宽<=高,求出有效的堆叠方式使得高度和最大。 我们直接按照第一个值从小到大进行排序,若相等按照第二个数继续,直至第三个数。这样排序后,对于某一个长方体 i i i来说,能够放在其上面的长方体的索引位置一定在其前面


至此,这道题目就很简单了,我们不用再去考虑如何进行旋转长方体。那么我们可以轻易的抽象出状态集合,类似于最长递增子序列问题。

 状态集合:
    dp[i]: 以第i个长方体结尾的堆叠方式能够获得的最大高度之和
状态计算:
    dp[i]: max(d[i], dp[j] + height[i]), if ok(i, j) , 0 <= j < i
    其中ok(i,j)代表hj <= hi, wj <= wi, lj <= li
  • 时间复杂度: O ( n 2 ) O(n^2) O(n2)
  • 空间复杂度: O ( n ) O(n) O(n)
class Solution {
    public int maxHeight(int[][] cub) {
        int n = cub.length, ans = 0;
        int[] dp = new int[n];
        for (int i = 0; i < n; i++) Arrays.sort(cub[i]);
        Arrays.sort(cub, (a, b) -> a[0] == b[0] ? (a[1] == b[1] ? a[2] - b[2] : a[1] - b[1]) : a[0] - b[0]);//从第一个元素从小到大进行排序,若相等按照第二个元素,若还相等按照第三个元素
        for (int i = 0; i < n; i++) { 
            dp[i] = cub[i][2];
            for (int j = 0; j < i; j++) {
                if (cub[i][1] >= cub[j][1] && cub[i][2] >=  cub[j][2]) dp[i] = Math.max(dp[i], dp[j] + cub[i][2]);
            }
            ans = Math.max(dp[i], ans);
        }
        return ans;
    }
}
class Solution {
public:
    int maxHeight(vector<vector<int>>& cub) {
        int n = cub.size(), ans = 0; 
        vector<int> dp(n, 0);
        for (auto& t : cub) sort(t.begin(), t.end());
        sort(cub.begin(), cub.end(), [](vector<int>& a, vector<int>& b){ return a[0] == b[0] ? (a[1] == b[1] ? a[2] < b[2] : a[1] < b[1]) : a[0] < b[0];});//从第一个元素从小到大进行排序
        for (int i = 0; i < n; i++) { 
            dp[i] = cub[i][2];
            for (int j = 0; j < i; j++) {
                if (cub[i][1] >= cub[j][1] && cub[i][2] >=  cub[j][2]) dp[i] = max(dp[i], dp[j] + cub[i][2]);
            }
            ans = max(dp[i], ans);
        }
        return ans;
    }
};

如果有问题,欢迎评论区交流, 如果有帮助到你,请给题解点个赞和收藏哈~~~

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

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

相关文章

计算机网络(自顶向下)—第八章习题

在下面的空格中填入“谁的什么密钥”&#xff1a; &#xff08;1&#xff09; A 向 B 发送一个一次性会话密钥&#xff0c;A 用B的公钥加密该会话密钥。 &#xff08;2&#xff09; Certifier.com 用Certifier.com的私钥 为 foo.com 签发公钥证书。 &#xff08;3&#xff…

红队隧道应用篇之Neo-reGeorg实现内网穿透(四)

简介 reGeorg是一个能够实现内网穿透的工具&#xff0c;基于socks5协议&#xff0c;且能支持众多脚本 由于此工具使用率过高&#xff0c;导致容易被杀毒软件拦截, 现有一个项目是由reGeorg修改而来, 而且做了加密和免杀处理, 这款工具的名字就叫Neo-reGeorg Neo-reGeorg下载…

Python+Selenium+Unittest 之selenium1--环境搭建

对于学习一个新东西来说&#xff0c;最开始就是要搭建环境了&#xff0c;关于python的环境搭建这里就不说了&#xff0c;主要说下selenium的环境搭建相关内容和安装过程中可能遇到的坑&#xff0c;细节不太一致的可以自行百度解决下&#xff0c;本章所使用的版本为python3.9sel…

Xcode安装特定版本系统的模拟器(不支持断点下载所以总是下载失败)

Xcode里下载太慢就算了&#xff0c;他不支持断点下载&#xff0c;一直一直一直下载失败&#xff0c;根本就装不上嘛&#xff01;&#xff01;&#xff01; 添加模拟器、下载需要的iOS版本 添加模拟器 没有要的iOS版本则点击Download more 然而因为Xcode不支持断点下载&…

【C语言】内存操作函数

目录 一、memcpy函数 1、memcpy函数的用途 2、memcpy函数的使用 3、memcpy函数的模拟实现 二、memmove函数 1、memmove函数的用途 2、memmove函数的使用 3、memmove函数的模拟实现 三、memset函数 1、memset函数的用途 2、memset函数的使用 3、memset函数的模拟实现 四、memcmp…

React 入门:实战案例 TodoList 修改 Todo Item的状态

文章目录目标实现效果实现思路实现步骤第一步&#xff1a;定义更改 Todo 状态的方法&#xff0c;以供调用第二步&#xff1a;App 组件传递更改 Todo 状态的方法给子组件 List第三步&#xff1a;List 组件传递更改 Todo 状态的方法给子组件 Item第四步&#xff1a;Item 调用更改…

Spring 6.0 正式发布,一文了解新特性

正式发布 Spring Framework 6.0 首个 RC 版本正式发布&#xff0c;可以开始使用了。 新特性 我们一起来看看这次6.0版本带来了哪些特性&#xff1f;需要注意的是该版本整个框架代码库现在基于 Java 17 源代码级别&#xff0c;所以如果你想使用需要升级版本到 JDK 17 才可以&a…

什么是FPGA fpga的核心作用

fpga名词解释&#xff1a;FPGA是英文Field Programmable Gate Array的缩写&#xff0c;即现场可编程门阵列&#xff0c;它是在PAL、GAL、EPLD等可编程器件的基础上进一步发展的产物。 fpga核心做用&#xff1a;它是作为专用集成电路(ASIC)领域中的一种半定制电路而出现的&#…

【吴恩达机器学习笔记】十七、总结

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4e3;专栏定位&#xff1a;为学习吴恩达机器学习视频的同学提供的随堂笔记。 &#x1f4da;专栏简介&#xff1a;在这个专栏&#xff0c;我将整理吴恩达机器学习视频的所有内容的笔记&…

计算机毕业设计springboot+vue基本医院公众号建设推动医疗卫生服务现状研究

项目介绍 随着信息技术和网络技术的飞速发展,人类已进入全新信息化时代,传统管理技术已无法高效,便捷地管理信息。为了迎合时代需求,优化管理效率,各种各样的管理系统应运而生,各行各业相继进入信息管理时代,医院公众号建设推动医疗卫生服务就是信息时代变革中的产物之一。 任…

从零开始学Java之eclipse的安装配置与使用,看这篇就够了

前言 在上一篇文章中&#xff0c;壹哥给大家介绍了Notepad这个更高级点的记事本&#xff0c;它进行Java开发相比windows自带的记事本要更方便一些。但是即便如此&#xff0c;用这种记事本进行Java开发效率依然很低。如果是少量的代码编写还好说&#xff0c;大量代码的开发&…

计算机毕业设计springboot+vue基本微信小程序的电子书阅读器小程序

项目介绍 随着信息技术和网络技术的飞速发展,人类已进入全新信息化时代,传统管理技术已无法高效,便捷地管理信息。为了迎合时代需求,优化管理效率,各种各样的管理系统应运而生,各行各业相继进入信息管理时代,电子书阅读器小程序就是信息时代变革中的产物之一。 任何系统都要遵循…

【云原生】Kubernetes(k8s)Istio Gateway 介绍与实战操作

文章目录一、概述二、Istio 架构三、通过 istioctl 部署 Istio1&#xff09;安装istioctl 工具2&#xff09;通过istioctl安装istio3&#xff09;检查四、Istio Gateway五、Istio VirtualService 虚拟服务六、示例演示&#xff08;bookinfo&#xff09;1&#xff09;安装bookin…

MATLAB | 一起来感受数学之美,第一届迷你黑客大赛回顾

Hey真的是好久不见&#xff0c;最近确实是比较忙更新频率也下来了&#xff0c;过段时间应该能恢复正常更新速度&#xff0c;之前给大家解说过今年举办的math is beautiful迷你黑客大赛&#xff0c;但这其实是第二届大赛&#xff0c;本期推送带大家回顾一下第一期大赛&#xff0…

为什么索引可以让查询变快?终于有人说清楚了!

概述 人类存储信息的发展历程大致经历如下&#xff1a; 由于是个人凭着自己理解总结的&#xff0c;因此可能不一定精确&#xff0c;但是毋庸置疑的是&#xff0c;在当代&#xff0c;各大公司机构部门的数据都是维护在数据库当中的。 数据库作为数据存储介质发展的最新产物&am…

大数据面试之MapReduce常见题目

大数据面试之MapReduce常见题目 MapReduce中Shuffle过程及优化 1.1 Shuffle的详细图解 1.2 Shuffle的详细文字过程 Shuffle文字部分描述&#xff1a; ​ Shuffle横跨Map和Reduce阶段&#xff0c;是指map()方法之后&#xff0c;reduce()方法之前&#xff0c;中间这段汇洗的过…

Web前端大作业制作个人网页(html+css+javascript)

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

功能强大UI美观的视频答题猜歌闯关娱乐微信小程序源码下载

内容目录一、详细介绍二、效果展示1.部分代码2.效果图展示三、学习资料下载一、详细介绍 这是一款拥有后端的闯关娱乐小程序 支持个人小程序和企业小程序上线运营 功能强大齐全,带数据本地化 (数据在自己服务器自己管理无需担心第三方失效的问题) 支持看视频答题闯关 支持…

Java多线程处理笔记

学习视频:598-JavaSE进阶-多线程概述_哔哩哔哩_bilibili 目录 多线程概述 进程和线程的关系 多线程并发的理解 分析程序存在几个线程 实现线程的第一种方式 实现线程的第二种方式 采用匿名内部类的方式 线程生命周期 获取线程的名字 获取当前线程对象 线程的sleep方法 …

Spring Cloud Stream 结合rocketmq

Spring Cloud Stream 结合rocketmq 官方网址&#xff1a;https://github.com/alibaba/spring-cloud-alibaba/wiki/RocketMQ 你可以在这个地址上下载到相关示例项目&#xff0c;配置项等相关信息 spring-cloud-stream 文档&#xff08;这个地址似乎只有集合kafaka和rabbit的示…