给定一个n个数的数组,求其分成m个不相交子段和最大值的问题。很容易感觉是dp(咳咳。。从dp专题刷的题好意思说= =)
num是给定数组,dp[i][j]表示前i个数在选取第i个数的前提下分成j段的最大值,其中1<=j<=i<=n && j<=m,状态转移方程为
dp[i][j]=max(dp[i-1][j]+num[i],max(dp[0][j-1]~dp[i-1][j-1])+num[i])
仔细看就会发现dp[i][j]的求解只和dp[][j]与dp[][j-1]有关所以是可降维的,用两个一维即可。再进一步分析又能发现其实max(dp[0][j-1]~dp[i-1][j-1])也不需要单独求,即使更新就可以了。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int premax[1000001],num[1000001];
int n,m;
int DP()
{
int i,j,now;
for(i=1;i<=m;i++)
{
now=0;
for(j=1;j<=i;j++)
now+=num[j];
premax[n]=now;
for(j=i+1;j<=n;j++)
{
now=max(now,premax[j-1])+num[j];
premax[j-1]=premax[n];
premax[n]=max(now,premax[n]);
}
}
return premax[n];
}
int main()
{
int i,t;
while(scanf("%d%d",&m,&n)!=(EOF))
{
for(i=1;i<=n;i++)
{
scanf("%d",&num[i]);
premax[i]=0;
}
printf("%d\n",DP());
}
return 0;
}