现在的位置: 首页 > 综合 > 正文

杭电 1024

2013年02月16日 ⁄ 综合 ⁄ 共 986字 ⁄ 字号 评论关闭
/*
    经典的动态规划优化的问题。设f(i, j)表示前i个数划分成j段,且包括第i个数的最大m子段和,那么有dp方程:
    f(i, j) = max { f(i - 1, j) + v[i], max {f(k, j - 1) + v[i]}(k = j - 1 ... i - 1) }

    可以引入一个辅助数组来优化转移。设g(i, j)表示前i个数划分成j段的最大子段和(注意第i个数未必在j段里面),那么递推关系如下:
    g(i, j) = max{g(i - 1, j), f(i, j)}, 
    分是否加入第i个数来转移
  这样f的递推关系就变成:
    f(i, j) = max{f(i - 1, j), g(i - 1, j - 1)} + v[i],转移变成了O(1)
  这样最后的结果就是g[n][m],通过引入辅助数组巧妙的优化了转移。实现的时候可以用一维数组,速度很快
   
	g[i][j]要么和g[i-1][j]相等,要么和f[i][j]相等
	f[i][j]-a[i]要么和g[i-1][j-1]相等,要么和f[i-1][j]相等
	
	转成一维数组 到第i行时:f[j]=max{ f[j],g[j-1] }+a[i]
	                        g[j]=max{ g[j],f[j] };

*/
#include<iostream>
using namespace std;
int n,m;
const int N=1000001;
const int Min=-99999999;
int F[N],G[N];
int a[N];
int Max_num(int a,int b)
{
	if(a>b)
		return a;
	else return b;
}
int Min_num(int a,int b)
{
	if(a<b)
		return a;
	else return b;
}
int main()
{
	int i,j;
	while(scanf("%d%d",&m,&n)!=EOF && n && m)
	{
		for(i=1;i<=n;i++)
		{
			F[i]=Min;
			G[i]=Min;
			cin>>a[i];
		}
		F[1]=a[1];
		G[1]=a[1];
		for(i=2;i<=n;i++)
		{
			int t=Min_num(i,m);
			for(j=1;j<=t;j++)
			{
				F[j]=Max_num(F[j]+a[i],G[j-1]+a[i]);
				G[j-1]=Max_num(G[j-1],F[j-1]);
			}
			G[j-1]=Max_num(G[j-1],F[j-1]);
		}
		cout<<G[m]<<endl;
	}
	return 0;
}

抱歉!评论已关闭.