入门普通区间DP和环形区间DP

本文介绍了区间DP在处理大区间问题时的两种情况,即拆分子区间和合并连续区间,以及对应的解题模板和基本思路。同时详细讲解了环形区间DP的应用,通过实例展示了如何将环形结构转化为线性结构进行动态规划求解。
摘要由CSDN通过智能技术生成

什么情况的题目可以使用区间DP?一般有两种情况,第一种是可以将一个大区间的问题拆成若干个子区间合并的问题,还有一种是两个连续的子区间可以进行整合,合并成一个大区间。

基本的解题思路:

  1. 从小到大枚举区间长度。

  2. 对于每一个区间长度,枚举该长度的每一个区间。

  3. 对于每一个区间,枚举所有可能出现的两个子区间的组合。

  4. 对于每一个子区间的组合,计算出合并所需代价。

  5. 求出当前区间的最优值。例如f [i] [j]为区间[l,r]的最大价值,则f [i] [j] = max(f[i] [k] + f[k + 1] [r] + cost | l<=k < r)

基本模板:

for(int i= 1;i<=n;i++)
   {
     cin>>a[i];
     f[i][i] = 0;
     a[i] +=a[i-1];
   }
   for(int len = 2;len<=n;len++)
   {
     for(int i=1;i<=n - len +1;i++)
     {
       int j=i + len -1;
       for(int k = i;k < j;k++)
       {
         f[i][j] = min(f[i][j],f[i][k] + f[k+1][j] + a[j] - a[i-1]);
       }
     }
   }
   cout<<f[1][n]<< '\n';

在实现代码的时候,为啥是这样枚举区间?

for(int i = 1;i<=n;i++){
for(int j = i;j<=n;j++){
for(int k = i ;k < j;k++){
 f[i][j] = min(f[i][j], f[i][k] + f[k + 1][j] + sum(i,j));
}
}
}

如上图所示的枚举区间的方式有何问题?如下图解释:

 为了加深印象,我们利用一道例题来讲解,这道题有 n 堆石子排成一排,每堆石子有一定的数量。现在我们要将 n 堆石子并成为一堆,每次只能合并相邻的两堆石子,合并的花费为这两堆石子的总数。经过 n−1n−1 次合并后会成为一堆,求总的最小花费。这道题利用上面的模板就可以解决,其中dp[][]数组表示i ~ j组成的数组表示的最i到j堆合成一堆所用的最小花费,故本题输出dp[1][n]即可。

除了这种区间DP,还有一种为环形区间DP,顾名思义,即为区间是首尾相连的环形 ,这种DP方式存在一定的解题步骤:

  • 数据的处理方法是将原区间复制一份在后边,总长度x 2。

  • 枚举的方法与普通区间DP一致。

  • 统计答案时要枚举所有的答案区间,找出最优答案。、

我们同样利用一道例题来加深环形DP的思想,这道题就是处理环形区间的最优分割问题。

解题思路:

循环读取 n 个数值,并将这些数值复制到 v 数组的后半部分,以处理环形的情况

接下来是动态规划的计算部分。通过两层循环,遍历区间长度 len 从 2 到 n,以及每个长度下的所有区间 [i,j]。在每个区间中,通过枚举分割点 k,更新 f[i][j] 的最优值。具体的更新方式为:f[i][j] = max(f[i][j], f[i][k] + f[k + 1][j] + v[i] * v[k + 1] * v[j + 1]),其中 f[i][k] 表示区间 [i,k] 的最优解,f[k + 1][j] 表示区间 [k+1,j] 的最优解。

最后,通过遍历更新后的 f 数组,找出环形链表中最大的分割得到的乘积和。具体的做法是通过遍历索引 i,找到 f[i][i+n-1] 中的最大值,即为最终的答案。

基本模板内容:
 

 for(int i=1;i<=n;i++)
   {
     cin>>v[i];
     v[i + n] = v[i]; 
   } 
   for(int len = 2;len<=n;len++){
     for(int i=1;i + len -1 <= n * 2;i++)
     {
       int j = i + len -1;
       for(int k =i;k < j;k++)
       {
         f[i][j] = max(f[i][j], f[i][k] + f[k + 1][j] + v[i] * v[k + 1] * v[j + 1]);
       }
     }
   }
   int ans = 0;
   for(int i = 1;i <= n; i ++)
   {
     ans = max(ans, f[i][i+n - 1]);
   }

在这个解法中,通过将环形结构转化为线性结构,并利用动态规划的思想和状态转移方程,处理了环形区间的最优分割问题。

普通区间DP原题链接:

https://www.lanqiao.cn/problems/1233/learning/?page=1&first_category_id=1&problem_id=1233
环形区间DP原题链接:
https://www.lanqiao.cn/problems/557/learning/?page=1&first_category_id=1&problem_id=557

  • 14
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值