• HDU1024


    题目链接:https://vjudge.net/problem/HDU-1024

    解题思路:自己完全没有思路,于是去看了kuangbin大神的题解,看了半天才大概理解了,自己写了一版,然后发现跟题解几乎一毛一样。。。这一题得详详细细地写一篇题解,好好地思考总结一下。

      用num[]数组保存数据,n为数组中的元素总数,m为段数。

      dp[i][j]:在选取第j个数的前提下,将前j个数分成i段所能得到的最大值。

      则对于dp[i][j],有两种决策:1、将第j个数作为第i段的最后一个数(也即让其并在第i段上,并且第i段的最后一个数为第j-1个数;2、将第j个数作为第i段的第一个数(也即让其单独成段)。

      状态转移方程:dp[i][j]=max(dp[i][j-1] + num[j], max(dp[i-1][k] | 0<k<j) + num[j]);

      但是,因为1≤n≤1,000,000而且m的数据范围未知,我们很难开出这么大的dp[][]数组,这个时候需要用到滚动数组的技巧。先上核心代码:

     1           for(i=1;i<=m;i++)
     2           {
     3                   mmmax=-INF;      //对于每一个i,把 mmmax 初始为-INF,一方面,这个 mmmax 可以用来保存对于外层循环的这一个 i 值,把前 j-1 个数分成 i 段所能得到的最大值。
     4                   for(j=i;j<=n;j++)
     5                   {
     6                       dp[j]=max(dp[j-1]+a[j],mmax[j-1]+a[j]);  // dp[j-1] 相当于 dp[i][j-1] ,而 mmax[j-1] 即为 max(dp[i-1][k] | 0<k<j) , mmax[]数组利用记忆化的方式,方便地
     7                                        // 实现了这个功能。
     8 
     9                       mmax[j-1]=mmmax;            //另一方面, mmmax 也起到一个延迟标记的作用,对于内层循环的这一个 j 值 mmmax 保存了把前 j-1 个数分成 i-1 段所能得到的最大值(即直到
    10                       mmmax=max(mmmax,dp[j]);     //j对应的数的上一个数的最大值),用 mmmax 更新mmax[j-1],可使对于 j+1 (即内层循环的下一次操作),用到的 mmax[j+1-1]是当i = i-1
    11                                                    //(即外层循环的上一次操作)时所对应的 mmax[j] 
    12 
    13                   }    
    14          }      

      至此,这道题就讲的差不多了。

    AC代码(作者:kuangbin)

     1 #include<stdio.h>
     2 #include<algorithm>
     3 #include<iostream>
     4 using namespace std;
     5 #define MAXN 1000000
     6 #define INF 0x7fffffff
     7 int dp[MAXN+10];
     8 int mmax[MAXN+10];
     9 int a[MAXN+10];
    10 int main()
    11 {
    12     int n,m;
    13     int i,j,mmmax;
    14     while(scanf("%d%d",&m,&n)!=EOF)
    15     {
    16         for(i=1;i<=n;i++)
    17         {
    18             scanf("%d",&a[i]);
    19             mmax[i]=0;
    20             dp[i]=0;
    21         }
    22         dp[0]=0;
    23         mmax[0]=0;    
    24         for(i=1;i<=m;i++)
    25         {
    26                 mmmax=-INF;
    27                 for(j=i;j<=n;j++)
    28                 {
    29                     dp[j]=max(dp[j-1]+a[j],mmax[j-1]+a[j]);
    30                     mmax[j-1]=mmmax;
    31                     mmmax=max(mmmax,dp[j]);
    32                 }    
    33         }  
    34         printf("%d
    ",mmmax);  
    35           
    36     } 
    37     return 0;   
    38 }    
    View Code

    附上kuangbin签名:人一我百!人十我万!永不放弃~~~怀着自信的心,去追逐梦想!

    “这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”
  • 相关阅读:
    台式机安装无线网卡建立共享操作
    Mean shift
    拉格朗日乘子法
    凸集和凸函数
    图像插值法
    高斯平滑
    gamma校正
    SIFT feature
    VS2013+Win10+opencv3.0配置(包括opencv2.4.10版本)
    caffe添加自己编写的Python层
  • 原文地址:https://www.cnblogs.com/Blogggggg/p/7200088.html
Copyright © 2020-2023  润新知