POJ 1163 The Triangle 动态规划(由下至上+由上至下)双解

题目:

The Triangle
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 36792 Accepted: 22034

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

Source


题意:


在上面的数字三角形中寻找一条从顶部到底边的路径,使得路径上所经过的数字之和最大。路径上的每一步都只能往左下或右下走。只需要求出这个最大和即可,不必给出具体路径。
三角形的行数大于1小于等于100,数字为0 -99
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5


先来看看由下至上的解法:


由下至上算最大值时,思路很简单。

由下至上选择时,把大三角形看成只有三个数的小三角形,把小三角形的定点加上小三角形中数值最大的支点的和作为下一次的支点,层层递归即可



#include <iostream>
#include <cstdio>
using namespace std;

const int maxx=100+10;
int map[maxx][maxx];
int n;
int i,j;

int max(int x,int y)
{
    return x>y?x:y;
}

int dp( )
{
    for(i=n-1;i>=1;i--)
    {
        for(j=1;j<=i;j++)
        {
            map[i][j]=max(map[i+1][j],map[i+1][j+1])+map[i][j];///由下至上选择时,把大三角形看成只有三个数的小三角形,把小三角形的定点加上小三角形中数值最大的支点的和作为下一次的支点,层层递归即可
        }
    }
    return map[1][1];
}

int main( )
{
    cin>>n;
    for(i = 1;i <= n; i++)
    {
        for(j=1;j <= i; j++)
        {
            scanf("%d",&map[i][j]);///当输入的数据很大时,不要用cin 输入,cin 输入是很慢的,因为cin其实是个函数,他在输入的时候会自动匹配所输入数据的格式,匹配成功后才能输入,你可以想象每个输入的数据都要在一个函数中先扫一遍才能输入,这可以有多慢吗?但其实scanf不是最快的,更快的还有getchar,但大多数题目是不要求进行太深的读入优化的
        }
    }
    cout<<dp()<<endl;
    return 0;
}


如果是由上至下,那么就应该进行递归求解。


而且,在递归过程中必须做好标记,对已经求解出来的数进行记录,避免重复计算。


其实如果仔细看这个由上至下的递归,我们会发现,其实,他的本质也是由下至上DP的。


#include <iostream>
#include <cstdio>
using namespace std;

const int maxx=100+10;
int map[maxx][maxx];
int vis[maxx][maxx];
int n;
int i,j;

int max(int x,int y)
{
    return x>y?x:y;
}

int dp(int x,int y)
{
    if(vis[x][y]!=-1)
    {
        return vis[x][y];
    }
    if(x==n)
    {
        vis[x][y]=map[x][y];
    }
    else
    {
        int kx=dp(x+1,y);
        int ky=dp(x+1,y+1);
        vis[x][y]=max(kx,ky)+map[x][y];
    }
    return vis[x][y];
}

int main( )
{
    cin>>n;
    for(i = 1;i <= n; i++)
    {
        for(j=1;j <= i; j++)
        {
            scanf("%d",&map[i][j]);
            vis[i][j]=-1;
        }
    }
    cout<<dp(1,1)<<endl;
    return 0;
}

如有BUG请指出,不胜感激。。。。。。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值