HUD 1024 Max Sum Plus Plus

题意:从一个序列中选出分成不交叉的m段 的最大和

解析 : 题目中 1 <= n <=1000000 所以二维数组是不能用了  所以 要想到简化为一维

dp[i][j]表示以i结尾的前i个数 分成j组的最大和  对于一个数A[i] 我们有两种选择,一是与第(i-1)个数在一组 或者 自成一组  ,所以状态方程就出来了

dp[i][j] = max(dp[i-1][j] + A[i], max(dp[k][j-1] {k| 1<= k <= i-1} ))    

max(dp[k][j-1] {k| 1<= k <= i-1} 表示前i-1个数组成的j-1组的最大值

通过状态方程 我们可以发现 其实dp[i][j]的求解只和dp[*][j]与dp[*][j-1]有关所以本题只需要两个一维数组即可搞定状态转移。

#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdio>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn = 1000010,INF = 0xfffffff;
int main()
{
    int n,m;
    int A[maxn];
    int pre[maxn];
    int dp[maxn];
    while(~scanf("%d%d",&m,&n))
    {
        mem(pre,0);
        mem(dp,0);
        for(int i=1; i<=n; i++)
            scanf("%d",&A[i]);
        int maxx = -INF;
        for(int i=1; i<=m; ++i)
        {
            maxx = -INF;
            for(int j=i; j<=n; ++j)
            {
                dp[j] = max(dp[j-1], pre[j-1]) + A[j];     //用pre[j-1] 表示前j-1个数选出i-1组的和的最大值  因为每次我们是在更新dp[j]之后才更新pre[j-1] 
                pre[j-1] = maxx;                //在第i次更新dp[j] 时 pre[j-1] 用的仍然是 第i-1次时的值  这就保证了 pre[j-1] 表示的是
                maxx = max(maxx,dp[j]);              // 前i-1个数组成的j-1组的最大值
            }
        }
        printf("%d\n",maxx);
        
    }

    return 0;
}

 

猜你喜欢

转载自www.cnblogs.com/WTSRUVF/p/9062577.html