[简单DP]Max Sum Plus Plus HDU 102

   [简单DP]Max Sum Plus Plus HDU 102
题目大意,给你N个数字,要求分为m段不相交的字段,求总和最大。
例如,-1、 4、 -2、 3、 -2、 3、6个数字,分成两个子段的话,我们可以分成4一段,3、-2、3一段,这样总和为8最大。

分析:第一次看到这道题的时候自己不会,参考网上的题解做的。今天是第二次做,打算好好分析下。

很显然,这是一道DP。

首先去考虑它的状态,有两个变量,n个数字,分成m段,那么我们可以定义数组dp[i][j],表示把前j个数字分成i个子段,最大和是多少。

基于状态,我们去考虑状态转移方程。

很显然,j>=i,不然无法分成i段。

i==j时,第j个数肯定是作为第i段的第一个数字的,那么答案就是前[i-1]段的最大值加上num[j]。(在这里,取[i-1]段的最大值,我们需要通过枚举dp[i-1][t],i<=t<=j-1得到,因为在分割的过程中,某些数字可能不会用到,dp[i-1][j-1] 不一定是最大值)
dp[i][j]=dp[i-1][t]+num [j](i<=t<=j-1);


i<j时,num[j]既可以作为第i段的开始,也可以作为第i段的结束,如果是开始,那么就是dp[i][j]=dp[i-1][t]+num[j](i<=t<=j-1),如果是结束,dp[i][j]=dp[i][j-1]+num[j];

所以,基本的状态转移方程:


      dp[i][j]=max(dp[i-1][t],dp[i][j-1])+num[j];


题目给的n为1e6,m未知,上述算法的时间复杂度接近O(m*n^2),空间复杂度为n*m,很显然会超时超内存,所以我们要优化。


算法优化:
    时间优化,不难发现,对于dp[i][t],在求dp[i][j]时,我们可以维护得到dp[i][t],存下来给dp[i+1][j+1]使用。这样,时间复杂度为O(m*n)。定义data[j-1],存储dp[i-1][t]的最大值。
    空间优化,对于 dp[i][j]=max(dp[i-1][t],dp[i][j-1])+num[j],dp[i-1][t] 我们已经       使用data[j-1]替换,因此,对于dp[i][j] 利用滚动数组优化为dp[j]。  

    这样状态转移方程变为:

    dp[j]=max(dp[j-1],data[j-1])+num[j];

    时间O(M*N),空间O(n)

#include<stdlib.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#include<queue>
using namespace std;
int dp[1000005],data[1000005];
int num[1000005];
int main()
{
    int m,n;
    while(~scanf("%d  %d",&m,&n))
    {
       memset(dp,0,sizeof(dp));
       memset(data,0,sizeof(data));
       for(int i=1;i<=n;i++)
        scanf("%d",&num[i]);
        int Max;
        for(int i=1;i<=m;i++)
        {
           Max=-999999999;
           for(int j=i;j<=n;j++)
           {
             if(i==j)
              dp[j]=dp[j-1]+num[j];
             else
              dp[j]=max(dp[j-1],data[j-1])+num[j];
              data[j-1]=Max;
              if(dp[j]>Max)
               Max=dp[j];

           }
        }
        printf("%d\n",Max);
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值