【HDU】 `1024 Max Sum Plus Plus

Max Sum Plus Plus



  • 题目大意

之前有个问题是让你求n个数的最大子段和,现在这个问题是让你求n个数的m段最大子段和…..


  • 题解

比之前那个问题更加复杂了,可以看到一段变成了m段,不能再像之前那样直接记录结果了。因为现在是分成了m段,所以我们增加一维方便定义状态:

我们用 d[i][j]表示分成i段,以j结尾的最大子段和。于是我们有转移方程
d[i][j]=max(d[i][j-1], 分成i-1段 到j-1时的解 )+a[j]
注意这里黑体的部分是分成i段,到j-1时的解而不是d[i-1][j-1]。所以我们用另外一个数组来记录解,我这里用的ans,递推方法与max sum如出一辙,这里就不说了。


  • 代码
#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int a[1000005],m,n,d[2][1000005],ans[2][1000005];

int main()
{
    while (scanf("%d%d",&m,&n)!=EOF)
    {
        memset(a,0,sizeof(a));
        memset(d,0,sizeof(d));
        memset(ans,0,sizeof(ans));
        for (int i=1;i<=n;i++) scanf("%d",&a[i]);
        for (int i=1;i<=m;i++)
            for (int j=1;j<=n;j++)
        {
            if (i==j)
            {
                d[i%2][j]=d[(i-1)%2][j-1]+a[j];
                ans[i%2][j]=d[i%2][j];
            }
            if (j>i)
            {
                d[i%2][j]=max(d[i%2][j-1],ans[(i-1)%2][j-1])+a[j];
                ans[i%2][j]=max(ans[i%2][j-1],d[i%2][j]);
            }
        }
        printf("%d\n",ans[m%2][n]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值