【原】 POJ 1163 The Triangle 三角形最大路径 动态规划 解题报告

 

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

 

方法:
DP:将大问题转化为小问题解决。由递归写循环。
c[i][j]表示从a[1][1]开始到a[i][j]的最大和。而最终的结果为c[n][1...n]中的最大值
递归式为:
c[1][1] = a[1][1]
c[i][j] = max{ c[i-1][j-1], c[i-1][j] } + a[i][j]
maxsum = argmax(j){ c[n][1...n] }

<1>最优子结构:如果c[i][j]是从a[1][1]开始到a[i][j]的最大和,那么c[i-1][j-1]和c[i-1][j]也
               是到a[i-1][j-1]和a[i-1][j]的最大和。
证明:设maxsum[i]=k是从a[1][1]开始到a[i][j]的最大和,则c[i][j]=k。
      当c[i-1][j-1]>c[i-1][j]时:
      c[i][j]=c[i-1][j-1]+a[i][j],因此k-a[i][j]为从a[1][1]开始到a[i-1][j-1]的一条路径长。
      下面要证明k-a[i][j]为从a[1][1]到a[i-1][j-1]的最大值。
      设w是一条从a[1][1]到a[i-1][j-1]更大的路径,|w|>k-a[i][j]。然后cut and past,则从
      a[1][1]开始到a[i][j]的一条更长的路径为w||a[i][j],此时该路径值大于k。与假设相矛盾,
      所以c[i-1][j-1]=a[i][j]
      当c[i-1][j-1]<c[i-1][j]时的情况可以同样得证。
<2>Overlapping:例如i=6,j=7
                (6,7)
               /     \
              /       \
           (5,6)     (5,7)
            /\         /\
           /  \       /  \
        (4,5)(4,6) (4,6)(4,7)
可以发现(4,6)之后的子树有重叠产生

另一种dp:从下往上递推
c[i][j]表示由a[i][j]开始到三角形最底部的最大路径。最终结果为c[1][1]
递归式:
c[n][1...n] = a[n][1...n]
c[i][j] = max{ c[i+1][j] , c[i+1][j+1] } + a[i][j]

Description

7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
(Figure 1)

Figure 1 shows a number triangle. Write a program that calculates the highest sum of numbers passed on a route that starts at the top and ends somewhere on the base. Each step can go either diagonally down to the left or diagonally down to the right.

Input

Your program is to read from standard input. The first line contains one integer N: the number of rows in the triangle. The following N lines describe the data of the triangle. The number of rows in the triangle is > 1 but <= 100. The numbers in the triangle, all integers, are between 0 and 99.

Output

Your program is to write to standard output. The highest sum is written as an integer.

Sample Input

5

7

3 8

8 1 0

2 7 4 4

4 5 2 6 5

Sample Output

30

 

   1: #include <stdio.h>
   2: #include <iostream>
   3:  
   4: using namespace std ;
   5:  
   6: const int N = 101 ;
   7:  
   8: int a[N][N] ;
   9: int c[N][N] ;
  10:  
  11: //dp方法1
  12: void run3176()
  13: {
  14:     int n ;
  15:     int i,j ;
  16:     int max ;
  17:  
  18:     scanf( "%d", &n ) ;
  19:     for( i=1 ; i<=n ; ++i )
  20:     {
  21:         c[i][0] = 0 ;  //***
  22:         for( j=1 ; j<=i ; ++j )
  23:             scanf( "%d", &(a[i][j]) ) ;
  24:     }
  25:  
  26:     //***
  27:     c[1][1] = a[1][1] ;
  28:     for( i=2 ; i<=n ; ++i )
  29:     {
  30:         for( j=1 ; j<=i ; ++j )
  31:             c[i][j] = std::max( c[i-1][j-1], c[i-1][j] ) + a[i][j] ;
  32:     }
  33:  
  34:     max = c[n][1];
  35:     for( i=2 ; i<=n ; ++i )
  36:         max = max>c[n][i] ? max : c[n][i] ;
  37:  
  38:     printf( "%d\n", max ) ;
  39: }
  40:  
  41: //dp方法2:从下往上递推
  42: void run1163_2()
  43: {
  44:     int n ;
  45:     int i,j ;
  46:  
  47:     scanf( "%d", &n ) ;
  48:     for( i=1 ; i<=n-1 ; ++i )
  49:     {
  50:         for( j=1 ; j<=i ; ++j )
  51:             scanf( "%d", &(a[i][j]) ) ;
  52:     }
  53:  
  54:     for( j=1 ; j<=n ; ++j )
  55:     {
  56:         scanf( "%d", &(a[n][j]) ) ;
  57:         c[n][j] = a[n][j] ;
  58:     }
  59:  
  60:     for( i=n-1 ; i>=1 ; --i )
  61:     {
  62:         for( j=1 ; j<=i ; ++j )
  63:             c[i][j] = std::max( c[i+1][j] , c[i+1][j+1] ) + a[i][j] ;
  64:     }
  65:  
  66:     printf( "%d\n" , c[1][1] ) ;
  67: }
posted @ 2010-11-05 16:14  Allen Sun  阅读(432)  评论(0编辑  收藏  举报