题目描述:
给你一个数字三角形, 形式如下:
2
10 5
4 3 6
1 8 7 9
找出从第一层到最后一层的一条路,使得所经过的权值之和最小或者最大
算法1:
从顶到底层记忆每一步;
#include<iostream>
#define N 50
using namespace std;
int Max=0;
void fun(int a[N][N],int n,int k,int v,int sum){
if(k==n){
Max=sum>Max?sum:Max;
cout<<"n = "<<n<<" max = "<<Max<<endl;
return ;
}
else{
//cout<<"sum="<<sum<<endl;
int sum1=sum+a[k+1][v];
int sum2=sum+a[k+1][v+1];
fun(a,n,k+1,v,sum1); //分支
fun(a,n,k+1,v+1,sum2);
}
return ;
}
int main(){
int array[N][N];
int n,m;
while(cin>>n){ //输入三角形的行数
for(int i=0;i<n;i++){ //输入三角形数据
for(int j=0;j<=i;j++){
cin>>m;
array[i][j]=m;
}
}
for(int i=0;i<n;i++){ //输出三角形数据
for(int j=0;j<=i;j++){
cout<<array[i][j]<<" ";
}
cout<<endl;
}
fun(array,n,0,0,array[0][0]); //传参调用
cout<<"the max is "<<Max<<endl;
}
return 0;
}
注意:在分支的时候不能对比左右两步的大小来分支,也就是说不能每一次都选择最大的那一步,否则算出的结果并非是全局性的。因此这个算法的复杂度不低。所以需要算法2
算法2:
从底层到顶,每一步都通过比较下一层的左右两个元素来取大的记录。
#include<iostream>
#include<algorithm>
#define N 50
using namespace std;
int a[N][N];
int p[N][N];
int num;
int fun(int i,int j){
if(p[i][j]!=0){ //如果该值被记录过,则直接返回
return p[i][j];
}
if(i==num-1){ //如果到达了最底层,则返回底层元素
return p[i][j]=a[i][j];
}
return p[i][j]=a[i][j]+max(fun(i+1,j),fun(i+1,j+1)); //比较下一层的左右两个元素,择最大的保存为当前位置的值
}
int main(){
int n,m;
while(cin>>n){
for(int i=0;i<n;i++){
for(int j=0;j<=i;j++){
cin>>m;
a[i][j]=m;
}
}
for(int i=0;i<n;i++){
for(int j=0;j<=i;j++){
cout<<a[i][j]<<" ";
}
cout<<endl;
}
num=n;
cout<<fun(0,0)<<endl;
}
return 0;
}