zoukankan      html  css  js  c++  java
  • 【原】 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: }
  • 相关阅读:
    PAT 1088. Rational Arithmetic
    PAT 1087. All Roads Lead to Rome
    PAT 1086. Tree Traversals Again
    PAT 1085. Perfect Sequence
    PAT 1084. Broken Keyboard
    PAT 1083. List Grades
    PAT 1082. Read Number in Chinese
    求最大公因数
    [转载]Latex文件转成pdf后的字体嵌入问题的解决
    [转载]Matlab有用的小工具小技巧
  • 原文地址:https://www.cnblogs.com/allensun/p/1870225.html
Copyright © 2011-2022 走看看