数字金字塔(tower)

Description

观察下面的数字金字塔。写一个程序查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以从当前点走到左下方的点也可以到达右下方的点。

在上面的样例中,从 13 到 8 到 26 到 15 到 24 的路径产生了最大的和 86。

 

Format

Input

第一个行包含 R(1≤R≤1000),表示行的数目。

后面每行为这个数字金字塔特定行包含的整数。

所有的被供应的整数是非负的且不大于100。

Output

单独的一行,包含那个可能得到的最大的和。

Samples

Sample Input 1

5 
13
11 8
12 7 26
6 14 15 8
12 7 13 24 11

Sample Output 1

86

Solution

在这题中我们需要求金字塔的最长路径,要求全局最优解,所以这一题要用DP。

知道用DP,那就需要求解动态转移方程。

我们仔细观察,发现:

1,能到达 tower[i][j](j ≠ 1且j ≠ i),只有tower[i-1][j-1] 与 tower[i-1][j]。我们以下面一图中12、7、14作为例子。(画的图不太好,见谅)

其中 14 所在的位置是 tower[4][2],我们发现只有12和7能下一层选择14,12所在的位置是 tower[3][1],7所在的位置是 tower[3][2]。

2,能到达 tower[i][j](j = 1),仅有上一层金字塔的第一个元素,也就是 tower[i-1][j](j = 1)。我们以6,12作为例子。

其中12所在的位置是 tower[5][1],我们发现只有 6 能下一层选12,6所在的位置是 tower[4][1] 。

3,能到达 tower[i][j](j = i),仅有上一层金字塔的最后个元素,也就是 tower[i-1][j-1](j = i)。我们以13,8作为例子。

 其中8所在的位置是 tower[2][2],我们发现只有 13 能下一层选8,13所在的位置是 tower[1][1] 。

综上所述,我们就可以得到动态转移方程:

dp[i][j] = tower[i][j] + max(dp[i - 1][j - 1], dp[i - 1][j]) (j\neq1\&j\neq i)

 dp[i][j] = tower[i][j] + dp[i - 1][j](j = 1)

dp[i][j] = tower[i][j] + dp[i - 1][j - 1](j = i)

(因为我们要求最大值,所以当进行到第 i 行的两个数值较小的数值可以舍弃)

Code

#include <bits/stdc++.h>
using namespace std;
const int MAX_R = 1001;
int R, tower[MAX_R][MAX_R], dp[MAX_R][MAX_R];
int main(){
	scanf("%d", &R);
	for(int i = 1;i <= R; i++)								//输入 
		for(int j = 1;j <= i; j++)
			scanf("%d", &tower[i][j]);
	dp[1][1] = tower[1][1];									//第1行1列为起始点,dp数组就为本身的值 
	for(int i = 2;i <= R; i++)
		for(int j = 1;j <= i; j++){							//详见solution 
			if(j == 1)
				dp[i][j] = tower[i][j] + dp[i - 1][j];
			else if(j == i)
				dp[i][j] = tower[i][j] + dp[i - 1][j - 1];
			else
				dp[i][j] = tower[i][j] + max(dp[i - 1][j - 1], dp[i - 1][j]);
		}
	int res = -1;
	for(int j = 1;j <= R; j++)								//比较进行求出最下面一行数值的最大值,就为本题所求 
		res = max(res, dp[R][j]);
	printf("%d", res);
	return 0;
} 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值