好像没有看见一维版本(见第二份代码),故补充一份题解。
从上往下,朴素版
#include <iostream>
using namespace std;
const int N=510,INF=1e9;
int n;
int a[N][N]; //保存每个位置的值
int f[N][N]; //f[i][j]表示从(1,1)走到(i,j)的所有路径中,总和最大的那一条路径的总和
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
scanf("%d",&a[i][j]);
for(int i=1;i<=n;i++)
for(int j=0;j<=i+1;j++) //注意这里j从0到i+1,因为对于边界点,它的上一层只有一条路径通向它
f[i][j]=-INF; //初始化近似为-∞
f[1][1]=a[1][1]; //由f[i][j]的定义,(1,1)点的f值就是本身
for(int i=2;i<=n;i++) //这样,我们从第二层开始枚举至第n层
for(int j=1;j<=i;j++)
f[i][j]=max(f[i-1][j-1],f[i-1][j])+a[i][j];
int res=-INF;
for(int i=1;i<=n;i++) res=max(res,f[n][i]); //最大值在第n层的某一个点取得
printf("%d",res);
return 0;
}
从上往下,空间优化版,一维
#include <iostream>
using namespace std;
const int N=510,INF=1e9;
int n;
int f[N],a[N]; //f[j]表示从(1,1)走到(n,j)的所有路径中,总和最大的那一条路径的总和
int main()
{
scanf("%d",&n);
for(int j=0;j<=n+1;j++) //注意这里j从0到i+1,因为对于边界点,它的上一层只有一条路径通向它
f[j]=-INF; //初始化近似为-∞( 也可以memset(f,0xc0,sizeof f) )
scanf("%d",&f[1]); //由f[i][j]的定义,(1,1)点的f值就是本身
for(int i=2;i<=n;i++) //这样,我们从第二层开始枚举至第n层
{
for(int j=1;j<=i;j++) scanf("%d",&a[j]); //读入每层的值(不能与下面合并,因为下面是逆向的)
for(int j=i;j>=1;j--) f[j]=max(f[j-1],f[j])+a[j];
}
int res=-INF;
for(int i=1;i<=n;i++) res=max(res,f[i]); //最大值在第n层的某一个点取得
printf("%d",res);
return 0;
}
从下往上,无法优化成一维,因为需要预先读入全部数值
#include<iostream>
using namespace std;
const int N=510;
int f[N][N];
int n;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
scanf("%d",&f[i][j]);
}
}
for(int i=n;i>=1;i--){
for(int j=i;j>=1;j--){
f[i][j]=max(f[i+1][j],f[i+1][j+1])+f[i][j];
}
}
printf("%d",f[1][1]);
}
我这种只用开一个数组,左右颠倒不影响答案,初始化乱写的
第二种可以优化成一维,代码如下:
你在读取三角形的时候还是使用了二维数组噢
%%%%%%%%
%%%%%%%