原题链接:传送门
经典的dp问题 首先定义dp(i,j)代表从(i,j)出发时能得到的最大和(包括(i,j)本身的值。很容易得到
状态转移方程dp(i,j)=a(i,j)+max{d(i+1,j),d(i+1,j+1)},好了我们用朴素的递归去写。
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int n, a[N][N];
int d(int i, int j){
return a[i][j] + (i == n ? 0 : max(d(i + 1, j), d(i + 1, j + 1)));
}
int main(){
cin >> n;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= i; j++){
cin >> a[i][j];
}
}
cout << d(1, 1) << "\n";
return 0;
}
可以思考一下比如dp(3,2)它会被递归计算两次分别由d(2,2)和d(2,1),如果三角形是n层那么一共有2^n-1个节点这是必超的
所以我们可以采用记忆化搜索去优化已经遍历的节点
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int n, a[N][N], f[N][N];
int d(int i, int j){
if(f[i][j] >= 0) return f[i][j];
return f[i][j] = a[i][j] + (i == n ? 0 : max(d(i + 1, j), d(i + 1, j + 1)));
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n;
memset(f, -1, sizeof f);
for(int i = 1; i <= n; i++){
for(int j = 1; j <= i; j++){
cin >> a[i][j];
}
}
cout << d(1, 1) << "\n";
return 0;
}