HDU 1024 MAX sum plus plus

传送们:http://blog.sina.com.cn/s/blog_677a3eb30100jxqa.html

Author
JGShining(极光炫影)
思路:
dp[i][j]表示前j个元素分成i段的最优解,同时这个最优解是由a[j]元素结束的。
转移方程是dp[i][j]=max{f[i][j-1]+a[j],f[i-1][k]+a[j],(i-1<=k<j)} (i<=j<=n-m+i)
其中j的上下界的确定比较麻烦。现在分别解释上界和下界:
上界:dp[i][j]中,如果j=i-1,意思就是在前面i-1个元素中分成i段,这个是不可能实现的。
下界:如果m=n=4,这时dp[2][4]求出来了,意思是前面的四个元素分成了两段,当是还有两段要分,
      所以求出这个是没有意义的。当然求出来也不会影响结果,只是这样时间复杂度就提高了。
这是其中一个特例的状态转移表 m=4,n=6 ,-1 4 -2 3 -2 3
hdu <wbr>1024 <wbr>最大M子段和
没有填的说明不用算。
很显然dp[i][i]=dp[i-1][i-1]+a[i],
所以对角线上面有:
hdu <wbr>1024 <wbr>最大M子段和
现在演示一下转移过程。如何求下图的框中的元素的值
hdu <wbr>1024 <wbr>最大M子段和
由下面涂色的元素的最大值加上a[3]=-2求的如下图
hdu <wbr>1024 <wbr>最大M子段和

最大的是4,所以4+(-2)=2;框中填2;
假如框中的元素是dp[i][j],画圈的元素表示的是,左边那个是dp[i][j-1],上面的几个是dp[i-1][k](i-1<=k<j)} ,这个就是上面的转移方程的表格表示法。
 
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
__int64 a[1000010];
__int64 dp[2][1000010],ans;//设置滚动数组
int n,m;
__int64 MAX(__int64 a,__int64 b)
{
    return a>b?a:b;
}
int main()
{

    int i,j;
    while(scanf("%d %d",&m,&n)!=EOF)
    {

        for(i=1;i<=n;i++)
        {
            dp[0][i]=dp[1][i]=0;
            scanf("%I64d",&a[i]);
        }
        int pos=1;
        for(i=1;i<=m;i++)
        {
            dp[pos][i]=dp[pos^1][i-1]+a[i];//滚动数组,要进行初始化
            __int64 max=dp[pos^1][i-1];
            for(j=i+1;j<=n-m+i;j++)
            {
                max=MAX(max,dp[pos^1][j-1]);
                dp[pos][j]=MAX(dp[pos][j-1]+a[j],max+a[j]);
            }
            pos^=1;
        }
        pos^=1;
        ans=-99999999;
        for(i=m;i<=n;i++)
        {
            if(dp[pos][i]>ans)
            {
                ans=dp[pos][i];
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

posted on 2011-07-27 16:59  lonelycatcher  阅读(2212)  评论(0编辑  收藏  举报

导航