[dp]POJ 3176 Cow Bowling解题报告

来源:互联网 发布:绝地求生网吧优化 编辑:程序博客网 时间:2024/05/08 05:01

题目:
Cow Bowling
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 16077 Accepted: 10705
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
USACO 2005 December Bronze

方法一:从上往下dp

#include <iostream>#include<cmath>#include<cstring>#include<cstdio>using namespace std;int dp[355][355];//dp[i][j]表示牛走到第i行第j个元素时路径长度最大值int main(){    freopen("output.txt","w",stdout);    freopen("input.txt","r",stdin);    int N;    scanf("%d",&N);    for(int i=1;i<=N;i++){        for(int j=1;j<=i;j++){            scanf("%d",&dp[i][j]);        }    }    for(int i=2;i<=N;i++){//每行最左边和最右边的单独考虑        dp[i][1]+=dp[i-1][1];        dp[i][i]+=dp[i-1][i-1];    }    for(int i=2;i<=N;i++){//每行除了最左边和最右边,中间的部分        for(int j=2;j<=i-1;j++){            dp[i][j]+=max(dp[i-1][j-1],dp[i-1][j]);        }    }    int ans=-1;    for(int j=1;j<=N;j++)//在第N行找到最大值        ans=max(ans,dp[N][j]);    cout<<ans<<endl;    return 0;}

缺点:要单独考虑左右两边,最后还要遍历最后一行寻找结果。

方法二:从下往上dp,最后dp[1][1]就是答案。
优点:不用考虑特殊元素,过程简单明了
原理:原题是从上往下找权值最大的路径。因为这条路径如果存在,那么路径是可逆的,等效于从最下面找到达最上面的权值最大的路径,即从下往上dp。

#include <iostream>#include<cmath>#include<cstring>#include<cstdio>#define MAXN  70000using namespace std;int dp[355][355];int main(){    freopen("output.txt","w",stdout);    freopen("input.txt","r",stdin);    int N;    scanf("%d",&N);    for(int i=1;i<=N;i++){        for(int j=1;j<=i;j++){            scanf("%d",&dp[i][j]);        }    }    for(int i=N-1;i>=1;i--){        for(int j=1;j<=i;j++){            dp[i][j]+=max(dp[i+1][j],dp[i+1][j+1]);        }    }    cout<<dp[1][1]<<endl;    return 0;}

欢迎留言,积极讨论,一起进步!

0 0
原创粉丝点击