hdu 1024 Max Sum Plus Plus

主要参考这篇文章

http://hi.baidu.com/eizi/blog/item/3c12270987a4ad38e9248880.html


题意:

给你n个数的序列,从中取m段不相交的序列[ai,bi](1<=i<=m)使得这m段的和是所有可能中和最大的.


思路:

用dp[i][j]表示第i段以j结尾的最大值,两种情况:(1).将j连到以j-1为结尾的第i段后面;(2).a[j]单独作为第i段,那么第i-1段可能以i-1.....j-1 结尾.

状态转移方程: dp[i][j]=max{dp[i][j-1]+a[j] , dp[i-1][k]+a[j](i-1<=k<j) };

for(i=1;i<=m;i++)

for(j=1;j<=n;j++)

{

dp[i][j]=dp[i][j-1]+a[j];

for(k=i-1;k<j;k++)

dp[i][j]=max{ dp[i][j] , dp[i-1][k]+a[j] };

}

数据范围是1000,000三重循环无疑超时,分析容易知道第i段只和第i-1段的状态有关,

用 f[i] 表示当前处理的 i 段

用 pre[i-1] 表示当前处理之前的 i -1 段

所以 f[i] = max ( f[i-1] , pre[i-1] ) + a[j] ;

#include"stdio.h"
#define MAX 1000005
int a[MAX],f[MAX],pre[MAX];
int n,m,maxx;
int max(int x,int y)
{
	return x<y?y:x;
}
int main()
{
	int i,j;
	while(scanf("%d%d",&m,&n)!=-1)
	{
		for(i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
			pre[i]=f[i]=0;
		}
		f[0]=pre[0]=0;
		for(i=1;i<=m;i++)
		{
			maxx=-999999999;
			for(j=i;j<=n;j++)
			{
				f[j]=max(f[j-1],pre[j-1])+a[j];
				pre[j-1]=maxx;
				maxx=max(maxx,f[j]);
			}
		}
		printf("%d\n",maxx);
	}
	return 0;
}




原文地址:https://www.cnblogs.com/yyf573462811/p/6365352.html