数字三角形

题目:
给定一个由n行数字组成的数字三角形如下图所示。试设计一个算法,计算出从三角形
的顶至底的一条路径,使该路径经过的数字总和最大。(只能走正下 和 右下)
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
编程任务:
对于给定的由n 行数字组成的数字三角形,编程计算从三角形的顶至底的路径经过的数
字和的最大值。

解法一,普通递归:
用二维数组存放数字三角形。
D ( r , j ):第所亍第 j 个数字( r , j 从1开始算)
MaxSum ( r , j ):从 D ( r , j )到底边的各条路径中,最佳路径的数字之和。 问题:求 MaxSum (1,1)典型的递归问题。
有大量的重复计算,时间复杂度太高。``

#include
#include 
using namespace std;

#define MAX 101
int D[MAX][MAX];
int n;

int Maxsum(int i, int j)
{
	if(i==n){
		return D[i][j];
	}
	int x = Maxsum(i+1, j);
	int y = Maxsum(i+1, j+1);
	
	return max(x, y) + D[i][j];
}
int main()
{
	int i, j;
	cin >> n;
	for(i=1; i<=n; i++){
		for(j=1; j<=i; j++){
			cin >> D[i][j];
		}
	}
	cout << Maxsum(1, 1) << endl;
	
	return 0;
}

解法二,记忆型递归:
改进
如果每算出一个 MaxSum ( rj )就保存起来,下次用到其值的时候直接取用,则可免去重复计算。

#include
#include 
using namespace std;

#define MAX 101
int D[MAX][MAX];
int maxsum[MAX][MAX]; 
int n;

int Maxsum(int i, int j)
{
	if(maxsum[i][j] != -1){	//避免重复计算 
		return maxsum[i][j];
	}
	if(i==n){
		maxsum[i][j] = D[i][j];
	}else{
		int x = Maxsum(i+1, j);
		int y = Maxsum(i+1, j+1);
		maxsum[i][j] = max(x, y)+D[i][j];
	}
	
	return maxsum[i][j]; 
}
int main()
{
	int i, j;
	cin >> n;
	for(i=1; i<=n; i++){
		for(j=1; j<=i; j++){
			cin >> D[i][j];
			maxsum[i][j] = -1;
		}
	}
	cout << Maxsum(1, 1) << endl;
	
	return 0;
}

解法三,动态规划:
递归转成递推,先从底部的数字开始,从下到上。

#include
#include 
using namespace std;

#define MAX 101
int D[MAX][MAX];
int maxsum[MAX][MAX]; 
int n;

int main()
{
	int i, j;
	cin >> n;
	for(i=1; i<=n; i++){
		for(j=1; j<=i; j++){
			cin >> D[i][j];
		}
	}
	for(int i=1; i<=n; i++){
		maxsum[n][i]=D[n][i];
	} 
	for(int i=n-1; i>=1; --i){
		for(int j=1; j<=i; ++j){
			maxsum[i][j]=max(maxsum[i+1][j], maxsum[i+1][j+1]) + D[i][j];
		}
	}
	cout << maxsum[1][1] << endl;
	
	return 0;
}

还可以进行空间优化,不用二维 maxSum 数组存储每一个数,只要从底层一行行向上递推,那么只要一维数组 maxSum [100]即可,即只要存储一行的 MaxSum 值就可以。

你可能感兴趣的:(数字三角形)