USACO:1.5.1 Number Triangles 数字金字塔

★1.5.1 Number Triangles 数字金字塔

一、题目描述

考虑在下面被显示的数字金字塔.
写一个程序来计算从最高点开始在底部任意处结束的路径经过数字的和的最大.
每一步可以走到左下方的点也可以到达右下方的点.
        7
      3  8
    8  1  0
  2  7  4  4
4  5  2  6  5
在上面的样例中,从7 到 3 到 8 到 7 到 5 的路径产生了最大和:30
PROGRAM NAME: numtri
18
INPUT FORMAT
第一个行包含 R(1<= R<=1000) ,表示行的数目.
后面每行为这个数字金字塔特定行包含的整数.
所有的被供应的整数是非负的且不大于100.
SAMPLE INPUT (file numtri.in)
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
OUTPUT FORMAT
单独的一行包含那个可能得到的最大的和.
SAMPLE OUTPUT (file numtri.out)
30

二、解题思路

第一眼见到这个题,我们就要考虑这个题是什么类型?会用到什么算法?一般稍微有点算法基础的就知道,这是一个动态规划问题

在动态规划问题中,最重要的就是首先分析你所要关注的状态是什么,然后写出状态转移方程。在状态转移方程中,我们要清楚的明白状态方程的状态表达式是什么含义?是如何从上一状态转移到当前状态的?

对于本题,这是一个简单的动态规划问题(虽然简单,但我还是没想出来,大脑一片混乱。。。)。设f[i,j]表示到达第i层第j个最大的分数。 状态转移方程: f[i,j]=Max{f[i+1,j],f[i+1,j+1]}+a[i,j] (1<=i<=n-1,1<=j<=i)我们只需要知道下层的情况,所以可以用滚动数组来记录(降低空间复杂度),时间复杂度O(n^2),空间复杂度O(n)。(引自http://www.nocow.cn/index.php/USACO/numtri)

这里搜索的顺序是自下至上,主要是状态合并和更新的时候边界问题处理比较简单。同样,如果你想按常规的自上向下的顺序搜索,也是可以做出来的(USACO标准解就是这样的思路),不过状态数组的边界问题处理需要采取一些技巧。(其实也挺简单的)

下面是我的源代码

<span style="font-size:14px;">#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;

int max(int a,int b){
	return a>b ? a:b;
}
int num[1000][1000],f[1000];

int main(){
	freopen("numtri.in","r",stdin);
	//freopen("numtri.out","w",stdout);

	int R;
	int i,j;
	scanf("%d",&R);
	for (i=0;i<R;i++)
		for(j=0;j<i+1;j++)
			scanf("%d",&num[i][j]);

	for (i=0;i<R;i++)
		f[i]=num[R-1][i];

	for (i=R-1-1;i>=0;i--)
		for (j=0;j<=i;j++)
		{
			f[j]=max(f[j],f[j+1])+num[i][j];}

cout<<f[0]<<endl;

return 0;
}</span>

        

由于自身是初学者,编程能力有限,未达到专业程序员的水平,可能误导大家,请大家甄读;文字编辑也一般,文中会有措辞不当。博文中的错误和不足敬请读者批评指正。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝亦

感谢博主辛勤的付出

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值