有 N 堆石头排成一排,第 i 堆中有 stones[i] 块石头。

每次移动(move)需要将连续的 K 堆石头合并为一堆,而这个移动的成本为这 K 堆石头的总数。

找出把所有石头合并成一堆的最低成本。如果不可能,返回 -1 。

输入:stones = [3,2,4,1], K = 2
输出:20
解释:
从 [3, 2, 4, 1] 开始。
合并 [3, 2],成本为 5,剩下 [5, 4, 1]。
合并 [4, 1],成本为 5,剩下 [5, 5]。
合并 [5, 5],成本为 10,剩下 [10]。
总成本 20,这是可能的最小值。
输入:stones = [3,2,4,1], K = 3
输出:-1
解释:任何合并操作后,都会剩下 2 堆,我们无法再进行合并。所以这项任务是不可能完成的。.
输入:stones = [3,5,1,2,6], K = 3
输出:25
解释:
从 [3, 5, 1, 2, 6] 开始。
合并 [5, 1, 2],成本为 8,剩下 [3, 8, 6]。
合并 [3, 8, 6],成本为 17,剩下 [17]。
总成本 25,这是可能的最小值。

提示:

  • 1 <= stones.length <= 30
  • 2 <= K <= 30
  • 1 <= stones[i] <= 100

当K=2时,每次合并都是相邻的两堆进行合并。用dp[i][j]表示从i到j这个区间合并为1个堆时的最小代价。那么有转移方程:

dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1])

 //dp是从两两合并开始的,也就是说是长度先为2,然后3,....所以要枚举len的长度
//dp[i][j],len=j-i
for(int len=;len<n;len++)
{
for(int i=;i<=n-len;i++)
{
int j=i+len;
for(int k=i;k<j;k++)
{
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+][j]+sum[j]-sum[i-]);
}
}
}

通过观察上面的例子,我们可以知道K=2时,我们做的其实是将一部分合并为1堆,另一部分合并为1堆,最后形成一堆。典型的子问题划分问题,可以想象归并排序的过程。

现在K!=2了,那么我们就将一部分合并成K-1堆,另一部分合并成1堆,然后合并。

至于为什么不是K-2堆和2堆以及K-3堆和3堆是因为我们的子问题是合并成1堆,当前状态是由前一状态得到的。而我们最初只有dp[i][i][1]=0这个条件

现在K可以为任意值,由样例我们可以得到如果(n-1)%(k-1)不等于0的话,说明最终无法形成一堆。

现在考虑正常的情况,我们用dp[i][j][m]表示从i到j这个区间形成m堆所需的最小代价

初始化 dp[i][i][1]=0

dp[i][j][K]=min(dp[i][j][k],dp[i][k][K-1]+dp[k+1][j][1])

dp[i][j][1]=min(dp[i][j][K]+sum[j]-sum[k-1])

for (len=;len<=n;++len){
for (l=;l+len-<=n;++l)
{
r=l+len-;
for (k=l;k<r;++k)
{
for (i=;i<=len;++i)
{
f[l][r][i]=min(f[l][r][i],f[l][k][i-]+f[k+][r][]);
}
}
f[l][r][]=min(f[l][r][K]+sum[r]-sum[l-],f[l][r][]); }

Leetcode1000 合并石头的最低成本 区间DP的更多相关文章

  1. [Swift]LeetCode1000. 合并石头的最低成本 | Minimum Cost to Merge Stones

    There are N piles of stones arranged in a row.  The i-th pile has stones[i] stones. A move consists ...

  2. 区间DP(力扣1000.合并石头的最低成本)

    一.区间DP 顾名思义区间DP就是在区间上进行动态规划,先求出一段区间上的最优解,在合并成整个大区间的最优解,方法主要有记忆化搜素和递归的形式. 顺便提一下动态规划的成立条件是满足最优子结构和无后效性 ...

  3. nyoj 737 石子合并(一)。区间dp

    http://acm.nyist.net/JudgeOnline/problem.php?pid=737 数据很小,适合区间dp的入门 对于第[i, j]堆,无论你怎么合并,无论你先选哪两堆结合,当你 ...

  4. [NYIST737]石子合并(一)(区间dp)

    题目链接:http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=737 很经典的区间dp,发现没有写过题解.最近被hihocoder上几道比赛题难住了 ...

  5. 题解报告:NYOJ #737 石子合并(一)(区间dp)

    描述 有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆.求出总的代价最小值 ...

  6. NYOJ 737:石子合并(一)(区间dp)

    737-石子合并(一) 内存限制:64MB 时间限制:1000ms 特判: No 通过数:30 提交数:37 难度:3 题目描述: 有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆. ...

  7. 合并回文子串(区间dp)

    链接:https://ac.nowcoder.com/acm/problem/13230来源:牛客网 题目描述 输入两个字符串A和B,合并成一个串C,属于A和B的字符在C中顺序保持不变.如" ...

  8. HRBUST - 1819 石子合并问题--圆形版(区间dp+环形+四边形优化)

    石子合并问题--圆形版 在圆形操场上摆放着一行共n堆的石子.现要将石子有序地合并成一堆.规定每次只能选相邻的两堆合并成新的一堆,并将新的一堆石子数记为该次合并的得分.请编辑计算出将n堆石子合并成一堆的 ...

  9. 区间dp笔记√

    区间DP是一类在区间上进行dp的最优问题,一般是根据问题设出一个表示状态的dp,可以是二维的也可以是三维的,一般情况下为二维. 然后将问题划分成两个子问题,也就是一段区间分成左右两个区间,然后将左右两 ...

随机推荐

  1. Linux基础之常用命令整理(二)

    Linux系统启动流程 bios(找到启动介质) --> mbr(找到boot loader  512B 446引导信息 64分区信息 2 标志位 ) -->grub(选择操作系统或者内核 ...

  2. factory di

    services.AddScoped(typeof(Test)); //services.AddScoped<Test>() // .AddScoped<ITest, Test> ...

  3. tomcat9配置https

    首先去阿里云申请一个pfx证书,可以免费获得. 其次,在tomcat的server.xml增加如下connector <Connector port="443" protoc ...

  4. 如何避免在IE内核时,按BackSpace时进行网页会进行回退

    //解决在IE浏览器中input被设置成readonly时,点击Backspace时会出现网页回退 document.onkeydown = check; function check(e) { va ...

  5. 快速傅里叶变换(FFT)时间复杂度

    图:信号在时域上和频域上的直观表示 1. 计算一维离散傅里叶变换(DFT)公式如下: 其中,N表示数据长度.由上式可知,DFT的时间复杂度是O(N*N) 2. 一维FFT的时间复杂度为O(N*logN ...

  6. linux下导入、导出mysql数据库命令的实现方法

    首先建空数据库 mysql>create database abc; 导入数据库 mysql>use abc; 设置数据库编码 mysql>set names utf8; 导入数据( ...

  7. LoadRunner 安装汉化后的一些问题

    我装好LoadRunner11后,按照下面的方法破解: 1.  把loadrunner相关程序全部退出: 2.  用LR8.0中的mlr5lprg.dll.lm70.dll覆盖LR9.5安装目录下“b ...

  8. c#关于var的介绍和用法

    var关键字---根据初始化语句推断变量类型 功能: var关键字指示编译器根据初始化语句右侧的表达式推断变量的类型,推断类型可以是内置类型,匿名类型,用户定义类型,.NET Framework类库中 ...

  9. python大法好——多线程

    Python 多线程 多线程类似于同时执行多个不同程序,多线程运行有如下优点: 使用线程可以把占据长时间的程序中的任务放到后台去处理. 用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件 ...

  10. Mybatis pageHelper.startPage(...)是物理分页

    使用PageHelper.startPage(...)进行物理分页 业务需求只显示其中的100条数据 之前是在业务逻辑里对参数limit进行了处理 后来试试sql的limit查询100条数据 但是不确 ...