【动态规划】最大m子段和
2012-03-23 11:04
204 查看
给定n个数求这n个数划分成互不相交的m段的最大m子段和。
经典的动态规划优化的问题。设f(i, j)表示前i个数划分成j段,且包括第i个数的最大m子段和,那么有dp方程:
f(i, j) = max { f(i - 1, j) + v[i], max {f(k, j - 1) + v[i]}(k = j - 1 ... i - 1) }
也就是说第i个数要么自己划到第j段,要么和前一个数一起划到第j段里面,转移是O(n)的,总复杂度O(n * n * m)。
可以引入一个辅助数组来优化转移。设g(i, j)表示前i个数划分成j段的最大子段和(注意第i个数未必在j段里面),那么递推关系如下:
g(i, j) = max{g(i - 1, j), f(i, j)},分是否加入第i个数来转移
这样f的递推关系就变成:
f(i, j) = max{f(i - 1, j), g(i - 1, j - 1)} + v[i],转移变成了O(1)
这样最后的结果就是g
[m],通过引入辅助数组巧妙的优化了转移。实现的时候可以用一维数组,速度很快。
附HDU 1024题目代码:
经典的动态规划优化的问题。设f(i, j)表示前i个数划分成j段,且包括第i个数的最大m子段和,那么有dp方程:
f(i, j) = max { f(i - 1, j) + v[i], max {f(k, j - 1) + v[i]}(k = j - 1 ... i - 1) }
也就是说第i个数要么自己划到第j段,要么和前一个数一起划到第j段里面,转移是O(n)的,总复杂度O(n * n * m)。
可以引入一个辅助数组来优化转移。设g(i, j)表示前i个数划分成j段的最大子段和(注意第i个数未必在j段里面),那么递推关系如下:
g(i, j) = max{g(i - 1, j), f(i, j)},分是否加入第i个数来转移
这样f的递推关系就变成:
f(i, j) = max{f(i - 1, j), g(i - 1, j - 1)} + v[i],转移变成了O(1)
这样最后的结果就是g
[m],通过引入辅助数组巧妙的优化了转移。实现的时候可以用一维数组,速度很快。
附HDU 1024题目代码:
#include<cstdio> #include<algorithm> using namespace std; const int N=1000010,INF=0x3fffffff; int f ,g ,a ; int max_sum(int m,int n) { int i,j,t; for(i=1;i<=n;i++) { t=min(i,m); for(j=1;j<=t;j++) { f[j]=max(f[j],g[j-1])+a[i]; g[j-1]>?=f[j-1]; } g[j-1]>?=f[j-1]; } return g[m]; } int main() { int m,n; while(scanf("%d%d",&m,&n)==2&&m&&n) { for(int i=1;i<=n;i++) { f[i]=g[i]=-INF; scanf("%d",&a[i]); } printf("%d/n",max_sum(m,n)); } return 0; }
相关文章推荐
- POJ 2479(动态规划) [求最大子段和 的延伸]
- HDU1024 Max Sum Plus Plus 最大子段和(动态规划)
- 0013算法笔记——【动态规划】最大子段和问题,最大子矩阵和问题,最大m子段和问题
- 动态规划 HDU - 1003 Max Sum(最大子段和)
- 最大子段和 分治与动态规划
- 求数组的最大子段和,动态规划 时间复杂度O(n)
- 最大子段和——分治与动态规划
- 最大子段和——分治与动态规划
- DP 动态规划 Problem C 1003 最大递增子段和
- 洛谷Oj-最大子段和-动态规划
- 最大子段和(动态规划)
- 最大子段和——分治与动态规划
- C语言最大子段和问题(动态规划)
- 最大子段和——分治与动态规划
- 0013算法笔记——【动态规划】最大子段和问题,最大子矩阵和问题,最大m子段和问题
- 算法笔记——【动态规划】最大子段和
- 最大子段和(分治与动态规划典例)
- HDU1087 Super Jumping! Jumping! Jumping!(动态规划,最大递增子段和)
- 动态规划,最大子段和
- A - Max Sum Plus Plus HDU1024 ( 动态规划 多段连续子段和的最大值)