• 最长子序列dp poj2479 题解


    Maximum sum
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 44476   Accepted: 13796

    Description

    Given a set of n integers: A={a1, a2,..., an}, we define a function d(A) as below:
    Your task is to calculate d(A).

    Input

    The input consists of T(<=30) test cases. The number of test cases (T) is given in the first line of the input. 
    Each test case contains two lines. The first line is an integer n(2<=n<=50000). The second line contains n integers: a1, a2, ..., an. (|ai| <= 10000).There is an empty line after each case.

    Output

    Print exactly one line for each test case. The line should contain the integer d(A).

    Sample Input

    1
    
    10
    1 -1 2 2 3 -3 4 -4 5 -5

    Sample Output

    13

    简单的dp题。
    首先是dp,就是把大的问题细化为可以立即解决的小问题。

    这有点像数列:先确定n=1的情况,再确定n和n-1的关系,即可得出数列的通项公式。

    比如该题的寻找最大子序列,当n为1的时候很容易判定,取这唯一的一个值就好了,然后考虑n和n-1的关系。
    我们用a[n]来记录每个值,用dp[n]来记录过程。
    如果我们想由n-1的情况推出n的情况,我们是不是要知道n-1时前面的最大子序列和? 而且,这个 和 是需要包含a[n-1]这个值的,否则a[n]无法和前面的序列相连。

    思考之后我们可以的出,如果前面包含a[n-1]的最大子序列和,即dp[n-1],大于零,则我们可以得出:dp[n]=dp[n-1]+a[n] ,否则,dp[n]=a[n], 大于零就加上,有点贪心的感jio。
    也因此,dp[]中是存在负数的,因为我们要保证 dp[n-1] 至少要包含 a[n-1],否则无法相连,而且最大子序列 长度不能为0.

    但此时dp[] 是最终答案了吗?
    明显不是,因为 “最大子序列” 不要求每个dp[n-1]中包含a[n-1]。
    但也已经接近尾声了。
    我们可以知道,不管“最大子序列”在哪里结束,反正在 dp[n]前面的n-1 项中肯定存在,所以要求到dp[n]的最长子序列,只需从头到尾遍历更新一遍:

    for(int i=1;i<n;i++)
      if( dp[i-1] > dp[i] )
        dp[i]=dp[i-1]

    用l(左)数组和r(右)数组记录。

    好了,这样子左右分别来一遍后,我们分别得到了 l[]和r[] 两个数组,其中 l[t] 代表 【1,t】(闭区间)内的最大子序列和,r[t]则代表【t,n】的。

    而对于这题我们只需从1到n遍历一遍间断点相加 r[] 和 l[] 的值即可得到最大值。
    for(int i=1;i<n;i++)
    {
      ans= max ( ans , l[i-1]+r[i])
    }
    得出答案answer。
    有几个注意点:
    1 一个测试点n是最大值50000,所以需要开大一点的数组,我因为这个找了半天错= =。
    2 间断点本身只能取一次,被左或右取均可。

    贴一个网址,poj题目推荐
    https://www.cnblogs.com/rainydays/p/3671118.html

    类似题目,poj2593

    代码:
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <vector>
    #include <algorithm>
    using namespace std;
    const int maxn=50009;
    const int minn=-50000;
    
    int main()
    {
       // freopen("input.txt","r",stdin);
        int T,n,ans;
        int a[maxn],ls[2][maxn],rs[2][maxn];
        cin>>T;
        while(T--)
        {
              ans=minn;
              cin>>n;
              ls[0][0]=ls[1][0]=minn;rs[0][n+1]=rs[1][n+1]=minn;
              for(int i=1;i<=n;i++)
              {
                    scanf("%d",&a[i]);
                    ls[0][i]=max(ls[0][i-1]+a[i],a[i]);
                    ls[1][i]=max(ls[0][i],ls[1][i-1]);
              }
              for(int i=n;i>=1;i--)
              {
                    rs[0][i]=max(rs[0][i+1]+a[i],a[i]);
                    rs[1][i]=max(rs[0][i],rs[1][i+1]);
              }
    
              for(int i=2;i<=n;i++)
              {
                    ans=max(ans,ls[1][i-1]+rs[1][i]);
              }
              cout<<ans<<endl;
        }
    }
    

      

  • 相关阅读:
    hrbust 1788
    poj2299 ( bit )
    LA3027(并查集)
    hdu1166 (bit)
    hdu1598(并查集)
    cdoj1215 (并查集)
    hdu2643 ( 第二类斯特灵数 )
    hdu3625 ( 第一类斯特灵数 )
    Uva10066
    怎么处理sqlserver2017部署在winowsDocker上时区无法修改成功的方式,并且可以多创建新的容器调用简单的方式直接使用!
  • 原文地址:https://www.cnblogs.com/zgncbsylm/p/10569290.html
Copyright © 2020-2023  润新知