本文参考刘汝佳《算法竞赛入门经典》(第2版)
动态规划的核心是状态和状态转移方程
数字三角形 OpenJ_Bailian - 2760
【分析】
- 状态:d(i,j)表示从点(i,j)出发后能得到的最大和
- 状态转移方程:d(i,j)=max(d(i+1,j),d(i+1,j+1))
方法1(递归计算Time Limit Exceeded)
#include<iostream>
using namespace std;
const int maxn=105;
int a[maxn][maxn]={0};
int n;
void read(){
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
cin>>a[i][j];
}
}
}
int solve(int i,int j){
return a[i][j]+(i==n?0:max(solve(i+1,j),solve(i+1,j+1)));
}
int main()
{
read();
cout<<solve(1,1)<<endl;
return 0;
}
方法2(递推计算)
#include<iostream>
using namespace std;
const int maxn=105;
int a[maxn][maxn]={0};
int d[maxn][maxn];
int n;
void read(){
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
cin>>a[i][j];
}
}
}
void solve(){
for(int i=1;i<=n;i++) d[n][i]=a[n][i];
for(int i=n-1;i>=1;i--){
for(int j=1;j<=i;j++){
d[i][j]=a[i][j]+max(d[i+1][j],d[i+1][j+1]);
}
}
}
int main()
{
read();
solve();
cout<<d[1][1]<<endl;
return 0;
}
方法三(记忆化搜索)
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=105;
int a[maxn][maxn]={0};
int d[maxn][maxn];
int n;
void read(){
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
cin>>a[i][j];
}
}
}
int solve(int i,int j){
if(d[i][j]>=0) return d[i][j];
return d[i][j]=a[i][j]+(i==n?0:max(solve(i+1,j),solve(i+1,j+1)));
}
int main()
{
memset(d,-1,sizeof(d));
read();
solve(1,1);
cout<<d[1][1]<<endl;
return 0;
}