【原】 POJ 3176 Cow Bowling 动态规划 解题报告

 

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

 

方法:
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

The cows don't use actual bowling balls when they go bowling. They each take a number (in the range 0..99), though, and line up in a standard bowling-pin-like triangle like this:

7

3 8

8 1 0

2 7 4 4

4 5 2 6 5

Then the other cows traverse the triangle starting from its tip and moving "down" to one of the two diagonally adjacent cows until the "bottom" row is reached. The cow's score is the sum of the numbers of the cows visited along the way. The cow with the highest score wins that frame. 
Given a triangle with N (1 <= N <= 350) rows, determine the highest possible sum achievable.

Input

Line 1: A single integer, N 
Lines 2..N+1: Line i+1 contains i space-separated integers that represent row i of the triangle.

Output

Line 1: The largest sum achievable using the traversal rules

Sample Input

5

7

3 8

8 1 0

2 7 4 4

4 5 2 6 5

Sample Output

30

Hint

Explanation of the sample:

7

*

3 8

*

8 1 0

*

2 7 4 4

*

4 5 2 6 5

The highest score is achievable by traversing the cows as shown above.

 

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