zoukankan      html  css  js  c++  java
  • hdu 1024 最大m子段和

    注:摘的老师写的

    最大m子段和问题

    以-1 4 -2 3 -2 3为例
    最大子段和是:6
    最大2子段和是:4+(3-2+3)=8
    所以,最大子段和和最大m子段和不一样,不能用比如先求一个最大子段和,从序列中去掉已求子段,再求下一个最大子段和的方法,这种方法有点贪心的味道,但是不行。所以,还得用动态规划。

    1.基本思路:
      首先,定义数组num[n],dp[m][n]. 
      num[n]用来存储n个整数组成的序列. dp[m][n]代表n个整数序列求m个子段和。

      按照分阶段的思想,我们首先考虑最后一项,即num[n].num[n]属于最大m子段和只有两种情况,

      如果用搜索树表示的话,只有两个分支,

      一个是属于最大m子段和(肯定是第m子段),

     另一个是不属于(即最大m子段和在前n-1个整数中构成)。
      先说属于情况,即第m子段由num[n]结尾,又分两种情况:要么自己独立成一个子段,要么与前边以num[j-1]结尾的子段联合。所以,我们用b[m][n]表示最后一个子段以num[n]项结尾的最大m子段和。则
    b[m][n]=max{b[m][n-1]+num[n],b[m-1][t]+num[n]},其中后一项表示num[n]自己成一段,前面t个整数(以每个整数为子段最后一项)(1<=t<=n-1)。
      再说不属于情况,则dp[m][n]=dp[m][n-1],表示由n-1个整数构成m个子段和最大。(不包括num[n])
      综合这两种情况:
      dp[m][n]=max{b[m][n-1]+num[n],b[m-1][t]+num[n],dp[m][n-1]}
      推广一下:
      dp[i][j]=max{b[i][j],dp[m][n-1]}=max{b[i][j-1]+num[j],b[i-1][t]+num[j],dp[i][j-1]}
      dp[0][1]=dp[1][0]=0
      b[0][1]=b[1][0]=0
      
      以下,验证一下:
      以4 -2 3 -2 3为例
      dp[1][1]=max{b[1][0]+4,b[0][0]+4,0}=4  b[1][1]=4
      dp[1][2]=max{b[1][1]-2,(b[0][0],b[0][1])+4,dp[1][1]}=4    b[1][2]=4-2=2
      dp[1][3]=max{b[1][2]+3,(b[0][0],b[0][1],b[0][2])+4,dp[1][2]}=max{5,4,4}=5   b[1][3]=5
      dp[1][4]=max{b[1][3]-2,(b[0][0],b[0][1],b[0][2],b[0][3])+4,dp[1][3]}=max{3,4,5}=5  b[1][4]=3
      dp[1][5]=max{b[1][4]+3,(b[0][0],b[0][1],b[0][2],b[0][3],b[0][4])+4,dp[1][4]}=max{6,4,5}=6  b[1][5]=6

      dp[2][1]=0  b[2][1]=0
      dp[2][2]=max{b[2][1]-2,(b[1][0],b[1][1])-2,dp[2][1]}=max{-2,2,0}=2  b[2][2]=2
      dp[2][3]=max{b[2][2]+3,(b[1][0],b[1][1],b[1][2])+3,dp[2][2]}=max{5,7,2}=7  b[2][3]=7
      dp[2][4]=max{b[2][3]-2,(b[1][0],b[1][1],b[1][2],b[1][3])-2,dp[2][3]}=max{5,3,7}=7  b[2][4]=5
      dp[2][5]=max{b[2][4]+3,(b[1][0],b[1][1],b[1][2],b[1][3],b[1][4])+3,dp[2][4]}=max{8,8,7}=8  b[2][5]=8
      
      验证表明,分析正确。

      但是,我们会发现,当n非常大时,这个算法的时间复杂度和空间复杂度是非常高的,时间复杂度近似为O(m*n^2),
      空间复杂度近似为O(m*n).因此,我们需要优化算法来降低时间复杂度和空间复杂度.

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 using namespace std;
     5 int curr[1000001],pre[1000001],arr[1000001];
     6 const int MAX = -1000000001;
     7 int sum = 0;
     8 int main()
     9  {
    10     int m,n;
    11     while(cin>>m>>n)
    12     {
    13         memset(curr,0,sizeof(curr));
    14         memset(pre,0,sizeof(pre));
    15         for(int i=1;i<=n;i++)
    16             cin>>arr[i];
    17         int j=0;
    18         for(int i=1;i<=m;i++)
    19         {
    20             sum = MAX;
    21             for(j=i;j<=n;j++)
    22             {
    23                 curr[j] = max(curr[j-1],pre[j-1])+arr[j];
    24                 pre[j-1] = sum;
    25                 sum = max(sum,curr[j]);
    26             }
    27             pre[j-1] = sum;
    28 
    29         }
    30         cout<<sum<<endl;
    31     }
    32 }
    View Code
  • 相关阅读:
    showModalDialog 超过问题
    工作流,WEB框架,UI组件网络收集整理
    VSS使用方法详解
    Windows远程桌面连接命令mstsc
    Nginx 配置简述
    jQuery编程代码规范的最佳实践
    TinyMCE(富文本编辑器)在Asp.Net中的使用方法
    扣文转文方法
    VS2013 EMMET插件学习
    为革命保护视力 --- 给 Visual Studio 换颜色
  • 原文地址:https://www.cnblogs.com/xiaotian-222/p/5042505.html
Copyright © 2011-2022 走看看