HDU 1024 Max Sum Plus Plus(最大M子段和)

Description
给定一个数组,求其分成m个不相交子段和最大值
Input
多组输入,每组用例占一行,首先输入两个整数m和n表示子段数和序列长度,之后n个整数表示该序列,以文件尾结束输入
Output
对于每组用例,输出序列最大m子段和
Sample Input
1 3 1 2 3
2 6 -1 4 -2 3 -2 3
Sample Output
6
8
Solution
最大m子段和问题,经典dp
now[j]表示以第j个元素为结尾的i个子段的最大和,必须包含a[j]
pre[j]表示前j个元素i个子段的最大和,不一定包含a[j]。
dp[i][j]表示前j个元素i个子段的最大和,包含a[j]
原始状态转移方程:
dp[i][j]=max(dp[i][j-1],dp[i-1][k])+a[j] (i-1<=k<=j-1)
第1种情况是直接将第j个元素加在第i个子段之后,第2种情况是将第j个元素单独作为一个子段,那么前面必须是i-1个子段
这个题目由于n比较大,所以开不出dp数组,只有用滚动数组实现上述状态转移方程,用ans代替dp[i][j],则有下列状态转移方程
now[j]=max(now[j-1],pre[j-1])+a[j]
pre[j-1]=ans
ans=max(ans,now[j])
Code

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define maxn 1000005
#define INF 1<<29
using namespace std;
int a[maxn],now[maxn],pre[maxn],ans; 
int get_maxm(int n,int m)
{
    //初始化 
    memset(now,0,sizeof(now));
    memset(pre,0,sizeof(pre));
    for(int i=1;i<=m;i++)//枚举段数 
    {
        ans=-INF;//初始化 
        for(int j=i;j<=n;j++)
        {
            now[j]=max(now[j-1],pre[j-1])+a[j];
            pre[j-1]=ans;
            if(ans<now[j])
                ans=now[j];
        }
    }
    return ans;
}
int main()
{
    int n,m;
    while(~scanf("%d%d",&m,&n))
    {
        for(int i=1;i<=n;++i)
            scanf("%d",&a[i]);
        printf("%d\n",get_maxm(n,m));
    }
    return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值