zoukankan      html  css  js  c++  java
  • HDU-1024-Max Sum Plus Plus(DP)

    Max Sum Plus Plus

    HDU - 1024

    题意:

    给出一列n个整数,然后要把他们分成m段,使得m段的和最大。

    分析:

    把n个整数分成m段,还要让这m段的和最大

    d[i][j]表示前 i 个数在做选取第 i 个数的前提下,分成 j 段的最大值。(1<=j<=i<=n&&j<=m)

    d[i][j] = max(d[i-1][j]+a[i],max(d[j-1][j-1]~d[i-1][j-1])+a[i])

    第一备选项是d[i-1][j]+a[i],很容易理解,但是第二备选项,是要先求出分成 j-1段的最大值,然后再加上当前的a[i],这意味着是从j-1段增加一段到j段。所以我们只要把这个最大值,都保存下来就可以了。

    由于数目比较多,采用滚动数组的方法,但是如何求每分段的最大值呢?

    我们需要一个同样大的数组c,对于c[i-1][j-1],保存max(d[j-1][j-1]~d[i-1][j-1])。每一次决策d[i][j]之后,更新 c [i][j]

    转换成滚动数组之后,动态转移方程变成

    d[i] = max(d[i-1]+a[i],c[i-1]+a[i])

    但是需要注意,现在是在处理第 j 段的情况,但是我们用的 c 数组是保存着 j-1 段的情况,所以我们必须迟一步更新c数组,否则会影响到d数组的更新。先用 j-1 段的 c[i-1] 更新 d[i] ,然后利用储存 着 j 段max(d[1]~d[i-1])的 t 更新 j 段c[i-1],然后当更新完 c[i-1]之后,利用t = max(t,d[i])保存当前最大值,以便利于 j+1 段中d[i+1]的更新。

    #define MAX 1000010
    int a[MAX],d[Max],c[Max];
    int main() 
    {
        int m,n;
        while(cin>>m>>n)
        {
        	d[0] = 0;
        	for(int i=1;i<=n;i++)
        	{
        		scanf("%d",&a[i]);
        	}
        	memset(c,0,sizeof c);
        	memset(d,0,sizeof d);
        	int t=0;
        	for(int j=1;j<=m;j++)
        	{
        		t = -inf;//初始化每一阶段的最大值为t.
        		for(int i=j;i<=n;i++)
        		{
        			d[i] = max(d[i-1]+a[i],c[i-1]+a[i]);//每一次决策
        			c[i-1] = t;//更新当前段的最大值
        			t = max(t,d[i]);//更新当前的段的最大值。
        		}
        	}
        	cout<<t<<endl;
        }
        return 0;
    }
    
  • 相关阅读:
    Android 获取View在屏幕中的位置【转】
    算法学习资源 -- 2018年8月21日星期二
    Activity SingleInstance启动模式
    Android Studio添加aar依赖的两种方式
    Multiple dex files define Lcom/google/gson/internal/Streams$AppendableWriter$CurrentWrite;
    Android Studio添加aar依赖
    jdk-8u181-docs.chm -- 制作时间2018年8月12日
    大串中查找校串出现的次数(11)
    字符串反转(10)
    String类的替换方法(9)
  • 原文地址:https://www.cnblogs.com/1625--H/p/9766636.html
Copyright © 2011-2022 走看看