acm-区间dp

区间dp

 

区间DP主要是把一个大区间拆分成几个小区间,先求小区间的最优值,然后合并起来求大区间的最优值。

 

//一般区间DP实现代码

memset(dp, 0x3f, sizeof(dp));

for (int i = 1; i <= n; i++) //区间长度为1的初始化    dp[i][i] = 0;

for (int len = 2; len <= n; len++) //枚举区间长度

{    

for (int i = 1, j = len; j <= n; i++, j++) //区间[i,j]  

    {        

    //DP方程实现    

    }

}

第一种模型:

 

石子合并

 

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

 

 

 

分析:要求n个石子归并,我们根据dp的思想划分成子问题,先求出每两个合并的最小代价,然后每三个的最小代价,依次知道n个。

 

定义状态dp [ i ] [ j ]为从第i个石子到第j个石子的合并最小代价。

 

那么dp [ i ] [ j ] = min(dp [ i ] [ k ] + dp [ k+1 ] [ j ]) 

 

那么我们就可以从小到大依次枚举让石子合并,直到所有的石子都合并。

 

第二种模型:

 

括号匹配:

 

描述:给出一串的只有‘(’ ‘)’  '[‘  ']'四种括号组成的串,让你求解需要最少添加括号数让串中的所有括号完全匹配。

 

 

 

分析:我们求出这个串的最大匹配,然后串的总长度-最大匹配就是答案。

 

 

 

方法1:首先能想到的是转化成最长公共子序列,枚举中间点,求其中的最大值 * 2就是最大匹配。

 

 

 

方法2:

 

定义dp [ i ] [ j ] 为串中第 i 个到第 j 个括号的最大匹配数目

 

假如第 i 个和第 j 个是一对匹配的括号那么dp [ i ] [ j ] = dp [ i+1 ] [ j-1 ] + 2 ;

 

那么我们只需要从小到大枚举所有 i 和 j 中间的括号数目,然后满足匹配就用上面式子dp,然后每次更新dp [ i ] [ j ]为最大值即可。

 

更新最大值的方法是枚举 i 和 j 的中间值,然后让 dp[ i ] [ j ] = max ( dp [ i ] [ j ] , dp [ i ] [ f ] + dp [ f+1 ] [ j ] ) ;

 

第三种模型:

 

整数划分:

 

这种比较简单,不需要枚举区间k∈[i,j],这种类型只和左右边界相关。

 

描述:给出两个整数 n , m ,要求在 n 中加入m - 1 个乘号,将n分成m段,求出这m段的最大乘积

 

 

分析:根据区间dp的思想,我们定义dp [ i ] [ j ]为从开始到 i 中加入 j 个乘号得到的最大值。

 

那么我们可以依次计算加入1----m-1个乘号的结果

 

而每次放入x个乘号的最大值只需枚举第x个乘号的放的位置即可

 

dp [ i ] [ j ]  = MAX (dp [ i ] [ j ] , dp [ k ] [ j-1 ] * a [ k+1 ] [ i ] ) ;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值