• 【原】 POJ 2479 Maximum sum 动态规划 解题报告


    http://poj.org/problem?id=2479


    方法:两次dp+一次扫描,复杂度3*n
    基于求最大连续子数组的线性dp算法
    对数组从前往后各做一次O(n)的dp,求得maxsofar[0][0...n-1],再数组从后往前各做一次O(n)的dp,求得maxsofar[1][0...n-1],
    再扫描一遍maxsofar求得maxsofar[0][i-1] + maxsofar[1][i]的最大值,即为结果

    线性dp:将大问题转化为小问题来处理
    对于数组a[0...n-1],a[n-1]和最终结果max subarray a[i...j]之间的关系可能有三种情况:
    (1) i=j=n-1,则max subarray为a[n-1]
    (2) i<j=n-1,则max subarray为a[i...n-1]
    (3) i<j<n-1,则max subarray为a[i...j]
    设maxendinghere[i]表示a[0..i]中包含a[i]的子数组的最大和,maxsofar[i]表示a[0...i]中最大子数组的和
    因此可以看出大问题可转化为小问题来解决:a[0...i]的最大子数组的和是以下三者的最大值:
           a[i],a[0...i-1]中包含a[i-1]的最大子数组的和加a[i],a[0...i-1]的最大子数组的和
    递归式为:maxsofar[i] = max( a[i] ,  maxendinghere[i-1]+a[i] , maxsofar[i-1] )       

    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

    Hint

    In the sample, we choose {2,2,3,-3,4} and {5}, then we can get the answer. 
    Huge input,scanf is recommended.

       1: const int N = 50000 ;
       2:  
       3: int a[N] ;
       4: int maxsofar[2][N] ;
       5:  
       6: void run2479()
       7: {
       8:     int t,n,val ;
       9:     int i,j ;
      10:     int maxendinghere ;
      11:     int max ;
      12:     int sum ;
      13:  
      14:     scanf( "%d", &t ) ;
      15:     while( t-- && scanf( "%d", &n ) )
      16:     {
      17:         scanf( "%d", &a[0] ) ;
      18:         maxendinghere = a[0] ;
      19:         maxsofar[0][0] = a[0] ;
      20:         for( i=1 ; i<n ; ++i ) //输入数组的同时做从前往后的dp
      21:         {
      22:             scanf( "%d", &a[i] ) ;
      23:             maxendinghere = std::max( a[i] , maxendinghere+a[i] ) ;
      24:             maxsofar[0][i] = std::max( maxsofar[0][i-1] , maxendinghere ) ;
      25:         }
      26:  
      27:         maxendinghere = a[n-1] ;
      28:         maxsofar[1][n-1] = a[n-1] ;
      29:         max = maxsofar[0][n-2] + a[n-1] ;
      30:         for( i=n-2 ; i>0 ; --i ) //做从后往前的dp同时求得最大值
      31:         {
      32:             maxendinghere = std::max( a[i] , a[i]+maxendinghere ) ;
      33:             maxsofar[1][i] = std::max( maxsofar[1][i+1] , maxendinghere ) ;
      34:             sum = maxsofar[0][i-1] + maxsofar[1][i] ;
      35:             max = max>sum ? max : sum ;
      36:         }
      37:         printf( "%d\n" , max ) ;
      38:     }
      39: }
  • 相关阅读:
    ccBPM典型的树形表单和多表头表单的流程示例
    Arrays -数组工具类,数组转化字符串,数组排序等
    String
    ArrayList
    Random
    Scanner
    Phone-java标准类
    HelloWorld-java
    c++ 由无向图构造邻接表,实现深度优先遍历、广度优先遍历。
    c++实现哈夫曼树,哈夫曼编码,哈夫曼解码(字符串去重,并统计频率)
  • 原文地址:https://www.cnblogs.com/allensun/p/1870225.html
Copyright © 2020-2023  润新知