zoukankan      html  css  js  c++  java
  • HDU 1024 Max Sum Plus Plus ——(M段区间的最大和)

      感觉有点奇怪的是这题明明是n^2的复杂度,n=1e6竟然能过= =。应该是数据水了。

      dp[i][j]表示前j个数,分成i段,且最后一段的最后一个为a[j]的答案。那么转移式是:dp[i][j] = max(dp[i][j-1], max{dp[i-1][t]}) + a[j],(i-1<=t<=j-1,j-1>=i)。前者表示在第i段的最后一个加上a[j],后者表示a[j]另起一段。这个dp显然是可以滚动数组的,那么空间是可以接受的。然后后者可以使用一个pre数组来记录之前的最大值。具体见代码:

     1 #include <stdio.h>
     2 #include <algorithm>
     3 #include <string.h>
     4 using namespace std;
     5 const int N = 1000000 + 5;
     6 const int inf = 2e9;
     7 
     8 int m,n;
     9 int a[N],dp[N],pre[N];
    10 
    11 int main()
    12 {
    13     while(scanf("%d%d",&m,&n) == 2)
    14     {
    15         for(int i=1;i<=n;i++) scanf("%d",a+i);
    16         memset(pre,0,sizeof(pre));
    17         int temp;
    18         for(int i=1;i<=m;i++)
    19         {
    20             temp = -inf;
    21             for(int j=i;j<=n;j++)
    22             {
    23                 // 要加下面这行的特判,因为j和i相等的时候dp[j-1]是前一个i时候的状态
    24                 if(j == i) dp[j] = pre[j-1] + a[i];
    25                 else dp[j] = max(dp[j-1], pre[j-1]) + a[j];
    26                 pre[j-1] = temp; // 之所以只能这样更新是因为必须在旧状态的pre用完以后再更新新的pre
    27                 temp = max(temp, dp[j]);
    28             }
    29         }
    30         printf("%d
    ",temp);
    31     }
    32     return 0;
    33 }

      

      有几点想补充的。感觉如果用滚动数组,代码会更容易理解。个人认为上面这个特判不能少,因为j是必须大于i的,虽然少了也能过(应该是数据水了)。

    另外,还是觉得这题应当是n^2规模的问题。顺便回顾一下之前一道类似的问题:选k段,每段的长度都为m,求区间的最大和

  • 相关阅读:
    uoj388 【UNR #3】配对树
    uoj386 【UNR #3】鸽子固定器
    回忆录
    xcode 把项目代码提交到远程SVN服务器
    IOS 点击按钮拨号
    ADO与达梦7产生的一个未知问题
    DSN 建立达梦7(DM)连接
    iOS UIControl 事件的说明(转)
    IOS开发copy,nonatomic, retain,weak,strong用法
    QT Creator 使用SVN的版本号做为编译的版本信息
  • 原文地址:https://www.cnblogs.com/zzyDS/p/6393266.html
Copyright © 2011-2022 走看看