您的位置:首页 > 其它

hdu 1024 Max Sum Plus Plus

2016-05-02 16:20 232 查看
题意:在一个序列中,求出m个不相交的子序列,使这m个序列的和最大。

题意好理解,但递归方程的表示有些令我迷茫

看了下大牛们的题解,在这里说一下我的看法。

这里我结合代码来说一下:

dp[i][j]=Max(dp[i][j-1]+a[j] , max( dp[i-1][k] ) + a[j] ) 0<k<j)

dp[i][j] 表示前j个数分成i组时的最大值;

dp[i][j-1]+a[j] 表示(前i-1个数分成i组的最大值)+(第j个数),这意味着第j个数也属于第i组;

max(dp[i-1][k])+a[j] 0<k<j 表示(j前面的所有序列中分成i1组和最大的一个)+(第j个数),这意味着从第j个数开始为新的一组;然后加上前面i-1组的一共i组。

因为求max(dp[i-1][k])+a[j] 0<k<j 会因出现for循环而超时,所以考虑在分成i-1组的递归时就求出max(dp[i-1][k])0<k<j,

于是有下面公式

dp[j]=max(dp[j-1]+a[j],b[j-1]+a[j]);(因为上面dp[i][j-1]+a[i]仅用到当前行的dp值,所以完全可以用一维dp数组表示)

b[j-1]表示上面的max(dp[i-1][k])0<k<j。

请结合代码看

#include<iostream>
#include<algorithm>
#include<string.h>
#include<stdio.h>
using namespace std;
int a[1000010],dp[1000010],b[1000010];
int main()
{
int m,n,num=0,maxx;
while(scanf("%d%d",&m,&n)!=EOF)
{
for(int i=1; i<=n; i++)
cin>>a[i];
memset(dp,0,sizeof(dp));
memset(b,0,sizeof(b));
for(int i=1; i<=m; i++)
{
maxx=-(0x7fffffff);
for(int j=i; j<=n; j++)
{
dp[j]=max(dp[j-1]+a[j],b[j-1]+a[j]);
b[j-1]=maxx;
if(dp[j]>maxx)
{
maxx=dp[j];
}
}
}
cout<<maxx<<endl;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: