数字三角形
-
5 2 6 4 1 2 8 4 0 9 6 6 5 5 3 6
样例输出
-
28
问题描述
小Hi和小Ho在经历了螃蟹先生的任务之后被奖励了一次出国旅游的机会,于是他们来到了大洋彼岸的美国。美国人民的生活非常有意思,经常会有形形色色、奇奇怪怪的活动举办,这不,小Hi和小Ho刚刚下飞机,就赶上了当地的迷宫节活动。迷宫节里展览出来的迷宫都特别的有意思,但是小Ho却相中了一个其实并不怎么像迷宫的迷宫——因为这个迷宫的奖励非常丰富~
于是小Ho找到了小Hi,让小Hi帮助他获取尽可能多的奖品,小Hi把手一伸道:“迷宫的介绍拿来!”
小Ho选择的迷宫是一个被称为“数字三角形”的n(n不超过200)层迷宫,这个迷宫的第i层有i个房间,分别编号为1..i。除去最后一层的房间,每一个房间都会有一些通往下一层的房间的楼梯,用符号来表示的话,就是从第i层的编号为j的房间出发会有两条路,一条通向第i+1层的编号为j的房间,另一条会通向第i+1层的编号为j+1的房间,而最后一层的所有房间都只有一条离开迷宫的道路。这样的道路都是单向的,也就是说当沿着这些道路前往下一层的房间或者离开迷宫之后,小Ho没有办法再次回到这个房间。迷宫里同时只会有一个参与者,而在每个参与者进入这个迷宫的时候,每个房间里都会生成一定数量的奖券,这些奖券可以在通过迷宫之后兑换各种奖品。小Ho的起点在第1层的编号为1的房间,现在小Ho悄悄向其他参与者弄清楚了每个房间里的奖券数量,希望小Hi帮他计算出他最多能获得多少奖券。
输入
每个测试点(输入文件)有且仅有一组测试数据。
每组测试数据的第一行为一个正整数n,表示这个迷宫的层数。
接下来的n行描述这个迷宫中每个房间的奖券数,其中第i行的第j个数代表着迷宫第i层的编号为j的房间中的奖券数量。
测试数据保证,有100%的数据满足n不超过100
对于100%的数据,迷宫的层数n不超过100
对于100%的数据,每个房间中的奖券数不超过1000
对于50%的数据,迷宫的层数不超过15(小Ho表示2^15才3万多呢,也就是说……)
对于10%的数据,迷宫的层数不超过1(小Hi很好奇你的边界情况处理的如何?~)
对于10%的数据,迷宫的构造满足:对于90%以上的结点,左边道路通向的房间中的奖券数比右边道路通向的房间中的奖券数要多。
对于10%的数据,迷宫的构造满足:对于90%以上的结点,左边道路通向的房间中的奖券数比右边道路通向的房间中的奖券数要少。
输出
对于每组测试数据,输出一个整数Ans,表示小Ho可以获得的最多奖券数。
Source
My Solution
题意:dp基础题,给出一个数字三角形,求一条从顶到底的路径,路径权值和的最大值。
基础dp、朴素dp
复习下dp基础知识,
动态规划的一个核心概念在于不去计算已经计算的东西,不去计算不需要的东西,即"取出冗余"。
且要满足,性质一:无后效性,即当前的抉择不会对后面的抉择产生影响;
性质二:重复子问题,即把当前问题分解为k个问题。
然后定义状态,
写出状态转移方程,
并从时间和空间的角度优化 状态和状态转移方程。
然后注意处理边界情况。
这题直接定义 dpij表示走到第i层第j个房间时的 最大权值和,
dpij = max(dp[i-1][j-1], dp[i-1][j])
然后处理下左右边界即可。
复杂度 O(n^2)
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long LL;
const int MAXN = 1e2 + 8;
int w[MAXN][MAXN], dp[MAXN][MAXN];
int main()
{
#ifdef LOCAL
freopen("2.in", "r", stdin);
//freopen("2.out", "w", stdout);
#endif // LOCAL
ios::sync_with_stdio(false); cin.tie(0);
int n, i, j, ans = 0;
cin >> n;
for(i = 0; i < n; i++){
for(j = 0; j <= i; j++){
cin >> w[i][j];
}
}
for(i = 0; i < n; i++){
for(j = 0; j <= i; j++){
if(i == 0){
dp[i][j] = w[i][j];
}
else if(j == 0){
dp[i][j] = dp[i-1][j] + w[i][j];
}
else if(j == i){
dp[i][j] = dp[i-1][j-1] + w[i][j];
}
else{
dp[i][j] = max(dp[i-1][j-1], dp[i-1][j]) + w[i][j];
}
}
}
for(j = 0; j < n; j++) ans = max(ans, dp[n-1][j]);
cout << ans << endl;
return 0;
}
Thank you!
------from ProLights