写在前面
作为一个蒟蒻,最近开始进军DP受到了巨大阻力啊,总感觉脑子不够用。于是决定以一个蒟蒻的角度把自己的解题思路写出来,编为DP入门系列。评测网站为openjudge的百练那个域。
一、算法分析
首先考虑数塔的层数,显然题目上足足有一百层,显然用普通的搜索或者枚举是解决不了的,这里联想到DP的思路(注:在这里贪心也不行,因为目光太短浅)。那么如何能够既使得目光长远,又能降低算法复杂度呢?这里我们看题目,题目要求从上往下走,但是如果我们从上向下做的话,每一步都是未知的,也就违背了动态规划的无后效性原则。(这个原则可以理解为:“未来与过去无关”)。但是如果我们换一种思路,进行倒推,就可以满足动态规划的条件,从后往前,每次找两个子节点中较大的传给父节点,这样每次的“过去”都是最优的,有最优子结构和无后效性的性质。代码如下:
二、代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=151;
int a[maxn][maxn][4];
int n,i,j;
int main(){
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
cin>>n;
for(i=1;i<=n;i++)
for(j=1;j<=i;j++){
cin>>a[i][j][1];
a[i][j][2]=a[i][j][1];
//a[i][j][3]=0;
}
for(i=n-1;i>=1;i--)
for(j=1;j<=i;j++){
a[i][j][2]=max(a[i+1][j][2],a[i+1][j+1][2]);
a[i][j][2]+=a[i][j][1];
}
cout<<a[1][1][2];
return 0;
}