【算法详解】区间动态规划

区间动态规划的含义与模板解释

区间DP,其实求的就是一个区间内的最优值.
一般这种题目,在设置状态的时候,都可以设f[i][j]为区间i-j的最优值
而f[i][j]的最优值,这有两个小区间合并而来的,为了划分这两个更小的区间,我们则需用用一个循环变量k来枚举,而一般的状态转移方程便是: f [ i ] [ j ] = m a x / m i n ( f [ i ] [ j ] , f [ i ] [ k ] + f [ k ] [ j ] + s o m e t h i n g ) f[i][j]=max/min(f[i][j],f[i][k]+f[k][j]+something) f[i][j]=max/min(f[i][j],f[i][k]+f[k][j]+something)我们则需要根据这个题目的实际含义进行变通即可.
而区间dp的大致模板是:

for (int len=2;len<=n;len++)
    for (int i=1;i+len-1<=n;i++)
    {
        int j=i+len-1;
        for (int k=i;k<=j;k++)
            f[i][j]=max/min(f[i][j],f[i][k]+f[k][j]+something)
    }

len枚举区间的长度,i和j分别是区间的起点和终点,k的作用是用来划分区间.


石子合并

题目描述
在操场上沿一直线排列着n堆石子。现要将石子有次序地合并成一堆。
规定每次只能选相邻的两堆石子合并成新的一堆,并将新的一堆石子数计为该次合并的得分。 我们希望这n-1次合并后得到的得分总和最小。
输入格式
第一行有一个正整数n(n<=300),表示石子的堆数; 第二行有n个正整数,表示每一堆石子的石子数,每两个数之间用一个空格隔开。它们都不大于10000。
输出格式
一行,一个整数,表示答案。
样例数据
input
3
1 2 9
output
15

这道题其实就是一个区间DP的一个模板,即每次进行合并的时候就是合并一个区间.
我们可以设f[i][j]为合并i-j区间的石子的最优方案即最小花费,假设在我们进行i和j的状态转移的时候必然更小的区间已经求出了最优的方案数,那么我们只需要用k去划分石子数去进行状态转移即可.
因为本来的时间是O(n^3),我们则需要优化时间,采用前缀和的方法,把合并的数量进行计算即可.
我们可以得到状态转移方程: f [ i ] [ j ] = m i n ( f [ i ] [ j ] , f [ i ] [ k ] + f [ k + 1 ] [ j ] + c o s t [ i ] [ j ] ) f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+cost[i][j]) f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+cost[i][j])
表示两堆石子的合并花费加上新的花费得到的结果.
在代码实现上,我们需要注意:len是从2开始的,诸如f[1][1],f[2][2]都是不需要花费价值的,即初始值0;状态转移方程是f[i][k]+f[k&

  • 13
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值