动态规划学习系列——区间DP(二)
来源:互联网 发布:windows下方删工具栏 编辑:程序博客网 时间:2024/05/15 06:50
上一篇我们看了区间型DP的一道经典入门题——石子归并,这一次同样是类似的一道题——石子归并2
题目链接:wikioi 2102
题干不同之处在于,现在我们的石子不是排成一列了,而是围成一个环,我们要怎么把问题转化成普通的石子归并呢?
其实这是一种挺常见的算法技巧——变环为列
方法:长度为len的环 —> 长度为2*len的列
为什么这样变换是成立的呢?因为每一种截取顺序都可以在变换后的列出现。
通过这样一个方法,把一个环形DP变成了普通的DP了,这样就是普通的石子归并了,状态转移方程是:dp[i][j]=min(dp[i][j] , dp[i][k] + dp[k+1][j] + sum[i:j])
关键代码:
首先是预处理(变环为列……):
for(int i=1;i<=n;i++) scanf("%d",&a[i]);for(int i=1;i<=n;i++) a[i+n]=a[i];
接下来是记录连续和sum数组:
for(int i=1;i<=2*n;i++) sum[i]=sum[i-1]+a[i];
DP过程:
for(int len=2;len<=n+1;len++){ for(int i=1;i<=2*n-len+1;i++) { int j=i+len-1; for(int k=i;k<j;k++) { dp1[i][j]=max(dp1[i][j],dp1[i][k]+dp1[k+1][j]+sum[j]-sum[i-1]); dp2[i][j]=min(dp2[i][j],dp2[i][k]+dp2[k+1][j]+sum[j]-sum[i-1]); } }}
dp1数组代表最大代价,dp2数组代表最小代价(初始化要注意哦~)
完整的AC代码:
#include <bits/stdc++.h>#define INF 0x3f3f3f3fusing namespace std;int n,a[205],sum[205];int dp1[205][205],dp2[205][205];int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) a[i+n]=a[i]; memset(dp1,0,sizeof(dp1)); memset(dp2,INF,sizeof(dp2)); for(int i=1;i<=2*n;i++) dp2[i][i]=0; for(int i=1;i<=2*n;i++) sum[i]=sum[i-1]+a[i]; for(int len=2;len<=n+1;len++) { for(int i=1;i<=2*n-len+1;i++) { int j=i+len-1; for(int k=i;k<j;k++) { dp1[i][j]=max(dp1[i][j],dp1[i][k]+dp1[k+1][j]+sum[j]-sum[i-1]); dp2[i][j]=min(dp2[i][j],dp2[i][k]+dp2[k+1][j]+sum[j]-sum[i-1]); } } } int minx=INF,maxx=0; for(int i=1;i<=n;i++) { minx=min(minx,dp2[i][i+n-1]); maxx=max(maxx,dp1[i][i+n-1]); } printf("%d\n%d\n",minx,maxx); return 0;}
其实这不仅仅是区间DP的例题,而且是环形DP的例题,环形DP的基本思路和解法都是把环转化成普通的列,这种技巧不仅适用于DP,而且适用于各种字符串匹配的题。
0 0
- 动态规划学习系列——区间DP(二)
- 动态规划学习系列——区间DP(一)
- 动态规划学习系列——划分DP(二)
- 动态规划学习系列——数位DP(练手二)
- 动态规划学习系列——数位DP(初识)
- 动态规划学习系列——划分DP(一)
- 动态规划学习系列——划分DP(三)
- 动态规划学习系列——数位DP(练手一)
- 动态规划学习系列——数位DP(练手三)
- 动态规划学习系列——数位DP(练手四)
- 动态规划——数位dp入门(二)
- 动态规划_区间DP
- 【动态规划】常见区间dp
- 算法学习(二):动态规划(DP)(1)
- uva 10003 Cutting Sticks (动态规划:区间DP)
- 大坑!动态规划!SHU 1149 能量项链(区间DP)
- Vijos P1347 乘积最大(动态规划,区间DP)
- FZU 2177 ytaaa(区间dp动态规划)
- [LeetCode]Fraction to Recurring Decimal
- net Use命令详解
- hdu 1061 Rightmost Digit
- WOJ-Problem 1009 - The Legend of Valiant Emigration
- android开发常用命令总结
- 动态规划学习系列——区间DP(二)
- Class.forName的理解
- mysql日期和字符相互转换方法
- c#做一个锁屏软件
- MFC消息映射与命令传递
- 使用gitlab7.7.2需要注意的一些点
- 1、超酷的拜年产品,方便您送出新年祝福!
- 一个简单备份管理系统的实现
- 2、超酷的拜年产品,方便您送出新年祝福!