简单dp之——m段子序列的最大和

来源:互联网 发布:速达3000软件 编辑:程序博客网 时间:2024/06/06 06:25

题目:hdu1024

题意:m:分成m段。n:数组长度。给定一个数组求m段子区间的最大和

解答:dp[i][j]:前j个数分成i组的最大子区间和。

1、状态转移方程:dp[i][j] = max(dp[i][j-1] + a[j],max(dp[i-1][k](0 < k < j) ) + a[j])//前者:包含在第i组里,后者:独立成第i组

2、优化成一维的。

(1)将i放入外层循环当中

(2)如何求max(dp[i-1][k])?

dp[i-1][k]相当于上一轮(i-1)从dp(一维)[i-1]到dp[j-1]中的最大值,用t数组记录

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>using namespace std;const int MAXN = 1000000 + 100;const int INF = 0x7fffffff;int a[MAXN],dp[MAXN],t[MAXN];int temp,m,n;int main(){    while(~scanf("%d%d",&m,&n))    {        for(int i = 1;i <= n;i++)        {            scanf("%d",&a[i]);            t[i] = 0;            dp[i] = 0;        }        t[0] = 0;        dp[0] = 0;        for(int i = 1;i <= m;i++)        {            temp = -INF;//每进入新的一轮就要初始化为最小以便求该轮的最大值            for(int j = i;j <= n;j++)            {                dp[j] = max(dp[j-1] + a[j],t[j-1] + a[j]);                t[j-1] = temp;//求完dp[j]再更新                temp = max(temp,dp[j]);            }        }        int ans = -INF;        for(int i = m;i <= n;i++)            if(dp[i] > ans)                ans = dp[i];        printf("%d\n",ans);    }    return 0;}



0 0
原创粉丝点击