力扣leetcode1000.合并石头的最低成本

摘要:
这篇文章是对他人答案的解释。让我们根据石头的数量(即数组长度N)生成NxN的矩阵。从i到j的所有合成方法中最小值的假设数据如上图所示。只有下图中的深蓝色区域才是有效区域。如果左侧被定义为一块石头(原始的石头或合并的石头),公式①可以变形得到(left-1)/(K-1)=n,这也是一开始用来检查命题是否有效的公式,因此问题被分解为一个重复的子问题,即j]的最小组合值。

本文算是对其他人答案的解释吧

根据石头数量(即数组长度N)生成NxN的矩阵,每个位置 [i, j] 表示的含义为 i 到 j 的所有合成方式中的最小值

力扣leetcode1000.合并石头的最低成本第1张

  假设数据如上图所示,合成为三个一合并,那么,只有下图中深蓝色区域为有效区域,其他位置赋0。以第一行为例,0-0和0-1为无效合并,0-2为第一个有效的合并,直到0-6都是有效合并,第四行唯一有效的为4-6,这也是长度为3时最后一个有效的合并

力扣leetcode1000.合并石头的最低成本第2张

 那么,需要确定计算顺序,最后一次计算是 0-6 全部合并,即填入右上角那个格子,合并三个石头,这三个中其中两个可以是由其他石头合并来的,如下图左,也可以其中一个是由其他合并来的,另外两个来自最初的石头,如下图右,当然,如果石头更多,则可以全都来自于合并后的石头

力扣leetcode1000.合并石头的最低成本第3张

 但如果是K个合并,则问题会变得很复杂,因此将合并简化为左侧石头和右侧石头合并,并保证每侧都是有效的,如果将左侧定义为1个石头(原始的1个或者合并成后的一个),右侧为 K-1 个石头,这样左侧就有固定解了,而右侧长度小于原长度,即变为子问题,即

 step = K - 1, left = 1 + n * step  ①

 两侧的数量:[left, N - left]   ②   n取所有可能的值,例如在合并长度为7时,所有子问题为 [1, 6]、[3, 4]、[5, 2]  ③

 注:式①变形可得(left - 1) / (K - 1) = n,意为该长度有效,这也是最开始用来检测命题是否有效的公式

 这样就将问题拆解为重复子问题了,子问题为每个区间 [i, j] 的最小合并值,然后对②的所有子问题求最小值,即两侧分别为 1 个和 6 个、 3 个和 4 个、 5 个和 2 个时,哪种合并能得到最小值,然后子问题递归求解,而递归的逆运算即为递推(动态规划)了,dp 不会求解重复子问题,自然速度也快一些

 再对③推一层,假设 [3, 4] 是最小的解,这里面 3 是能够通过同样方式计算出来的,4 就有点不同,拆开是 [1, 3] 和 [3, 1] ,可以理解为一个存在解的石头 3 和一个多余的石头 1 ,计算时就用存在解的 3 的合并值额外加那 1 个石头的值即可,不存在额外的加分

 而额外加分指的是题目中的合并后需要将当前合累加进合并值,即 i 到 j 所有值累加后加到合并值上,观察最小子问题可发现,可以换一个角度理解什么时候需要额外加分,即假设 K = 5 ,已经存在一组合并好的石头,然后额外多 1 个、 2 个......这并不会额外加分,只用累加每个的值即可,如果这个是命题,则直接判否,直到额外多了 4 个,可以和最开始合并好的石头组成 5 个时,即可额外加分

因此,在后续每层计算时,采用相同的思路,如果没有达到倍数时,就单纯找到最小值,然后累加,当达到倍数时,额外加分,其中某些子问题不是真命题,但是有实际意义

附上代码 

https://www.jiuzhang.com/solution/minimum-cost-to-merge-stones/#tag-other-lang-python
 1 class Solution:
 2     def mergeStones(self, stones, K):
 3         n = len(stones)
 4 
 5         if (n - 1) % (K - 1) != 0:
 6             return -1
 7 
 8         f = [[0 for _ in range(n)] for _ in range(n)]
 9 
10         prefix = [0 for _ in range(n + 1)]
11         for i in range(n):
12             prefix[i + 1] = prefix[i] + stones[i]
13 
14         for l in range(K - 1, n):
15             for i in range(n - l):
16                 j = i + l
17                 f[i][j] = float('inf')
18                 for m in range(i, j, K - 1):
19                     f[i][j] = min(f[i][j], f[i][m] + f[m + 1][j])
20                 if (j - i) % (K - 1) == 0:
21                     f[i][j] += prefix[j + 1] - prefix[i]
22 
23         return f[0][n - 1]

免责声明:文章转载自《力扣leetcode1000.合并石头的最低成本》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇ArcEngine 坐标系变换bat命令查询硬件信息下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

使用linux mint 安装无线网卡驱动

新买了个笔记本Thinkpad E440,用了两天发现无线网非常不稳定,有时候能搜到wifi却连不上,有时候连上了却连不上互联网,于是决定重新安装个网卡驱动。 首先看看自己显卡的型号: lspci 04:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 P...

Android 开机问题知多少

极力推荐文章:欢迎收藏Android 干货分享 阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容: 一、 如何抓取开机问题Log 二、开机问题Log 分析流程 三、 kernel Log 搜索关键字fs_mgr 初步分析定位 四、uart lo...

oracle中监听程序当前无法识别连接描述符中请求服务 的解决方法

原因如下: 你oracle安装成功后,一直未停止数据库(即数据库是启动的),客户端配置成功后,应该一直不会有什么问题。 而一旦你和我同事一样,有时把Oracle安装在虚拟机中,而且Oracle安装完毕后,没在进行任何监听的配置,则虚拟机再启动,则就会出现ORA-12514的问题。如下图       如下是解决思路: 根据出错信息判断出客户端未监听...

Navicat使用常见的两个问题及解决方法,提高开发效率

Navicat使用常见问题 在我们日常开发过程中,一般不会直接使用命令行来操作 MYSQL 数据库,而会选择一些图形化界面去帮助我们来进行此类操作,常用的有:SQLyog(Logo也是小海豚),Navicat,或者直接使用编辑器自带的图形化界面工具。我这边开发使用的是 Navicat,在日常使用的时候出现过一下的问题: Too Many Connectio...

robotframework自动化测试框架搭建及问题汇总

1.安装python RF框架是基于python 的,所以一定要有python环境,python与rf存在兼容性问题,我安装的是python3.7.5,robotframework3.1.2。 选择添加到path,或者自己手动配置环境变量,打开cmd 输入python -V可以看到安装的版本 官网https://www.python.org/下载比较慢,...

Hive调优实战[转]

Hive优化总结 【转自:http://sznmail.iteye.com/blog/1499789】 优化时,把hive sql当做map reduce程序来读,会有意想不到的惊喜。 理解hadoop的核心能力,是hive优化的根本。这是这一年来,项目组所有成员宝贵的经验总结。   长期观察hadoop处理数据的过程,有几个显著的特征: 1.不怕数据多...