POJ-3176 Cow Bowling

Cow Bowling
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 19032 Accepted: 12653

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.

Source

题意:给定一个数塔,从数塔顶端向下走到塔底,问所经过的路径数字之和最大为多少。一道比较经典且入门级的DP问题,此题不能使用贪心,贪心只能得到近似最优解但不一定能够得到最优解。

思路:将数塔略微变形,可以得到一个下半三角矩阵,从数塔低端开始扫描,距离最近的两个数字两两配对求出和,一直向塔顶遍历,由于每次扫描都会求出这一层最大两数之和,所以回到塔顶后塔顶元素dp[0][0]即为所求答案。另外此题也可以使用递归函数解决,去掉塔顶元素,将下方元素分解成两个子塔,逐步划分到子塔的规模小于等于2  ,不过当数组规模过大则会TLE,递归函数无法通过OJ,拿来简单递归练手还是可以的(ノ・ω・)ノ゙

递归版:


a为所求下半三角矩阵,size为当前子塔的规模,line为当前元素行号,offset为当前元素列号

int towerrec(int a[MAX][MAX],int size,int line,int offset)//probably time limit exceeded,tower_rec
{
    if(size<=2)
        return a[line][offset]+max(a[line+1][offset],a[line+1][offset+1]);
    else
        return a[line][offset]+max(towerrec(a,size-1,line+1,offset),towerrec(a,size-1,line+1,offset+1));
}
AC版代码:

#include<iostream>
#define MAX 450
using namespace std;
int towerdp(int a[MAX][MAX],int n)//DP
{
    int i,j;
    int dp[MAX][MAX]={0};
    for(i=n-1;i>=0;i--)
        for(j=0;j<=i;j++)
            dp[i][j]=a[i][j]+max(dp[i+1][j],dp[i+1][j+1]);
    return dp[0][0];
}

int main()
{
    int n;
    int a[MAX][MAX]={0};
    cin >> n;
    int i,j;
    for(i=0;i<n;i++)
        for(j=0;j<=i;j++)
            cin >> a[i][j];
	cout << towerdp(a,n) << endl;
	return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值