| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 数据结构与算法 -> 2021-10-7 1049. 最后一块石头的重量 II(背包问题+动态规划) -> 正文阅读 |
|
[数据结构与算法]2021-10-7 1049. 最后一块石头的重量 II(背包问题+动态规划) |
注: 题目: 每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下:
最后,最多只会剩下一块 石头。返回此石头 最小的可能重量 。如果没有石头剩下,就返回 0。 示例 1: 提示: 题解: 其中 abcdijpq代表了石子编号,字母顺序不代表编号的大小关系。 如果不考虑「有放回」的操作的话,我们可以划分为两个石子堆(正号堆/负号堆):
这意味我们最终得到的结果,可以为原来 stonesstones 数组中的数字添加 +/? 符号,所形成的「计算表达式」所表示。 那有放回的石子重量如何考虑? 其实所谓的「有放回」操作,只是触发调整「某个原有石子」所在「哪个堆」中,并不会真正意义上的产生「新的石子重量」。 什么意思呢? 假设有起始石子 a 和 b,且两者重量关系为 a≥b,那么首先会将 a 放入「正号堆」,将 b 放入「负号堆」。重放回操作可以看作产生一个新的重量为 a?b 的“虚拟石子”,将来这个“虚拟石子”也会参与某次合并操作,也会被添加 +/? 符号:
因此所谓不断「合并」&「重放」,本质只是在构造一个折叠的计算表达式,最终都能展开扁平化为非折叠的计算表达式。 综上,即使是包含「有放回」操作,最终的结果仍然可以使用「为原来 stonesstones 数组中的数字添加 +/? 符号,形成的“计算表达式”」所表示。 有了上述分析后,问题转换为:为 stones 中的每个数字添加 +/?,使得形成的「计算表达式」结果绝对值最小。 需要考虑正负号两边时,其实只需要考虑一边就可以了,使用总和sum 减去决策出来的结果,就能得到另外一边的结果。 同时,由于想要「计算表达式」结果绝对值,因此我们需要将石子划分为差值最小的两个堆。 其实就是对「计算表达式」中带 ? 的数值提取公因数 ?1,进一步转换为两堆石子相减总和,绝对值最小。 这就将问题彻底切换为 1 背包问题:从 stones 数组中选择,凑成总和不超过 sum/2 的最大价值。 其中「成本」&「价值」均为数值本身。 整理一下: 定义 f[i][j] 代表考虑前 i 个物品(数值),凑成总和不超过 j 的最大价值。 每个物品都有「选」和「不选」两种决策,转移方程为: f[i][j]=max(f[i?1][j],f[i?1][j?stones[i?1]]+stones[i?1]) 与完全背包不同,01 背包的几种空间优化是不存在时间复杂度上的优化,因此写成 朴素二维、滚动数组、一维优化 都可以。 复杂度分析
滚动数组优化
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 6:29:38- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |