【原】 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: }

转载于:https://www.cnblogs.com/allensun/archive/2010/11/08/1872058.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值