题意:在一个序列中,求出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;
}
}