数字三角形(动态规划入门题)

题目描述

7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
(图1)

图1给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和。

注意:路径上的每一步只能从一个数走到下一层上和它最近的左边的那个数或者右边的那个数。
输入
输入的是一行是一个整数N (1 < N <= 100),给出三角形的行数。下面的N行给出数字三角形。数字三角形上的数的范围都在0和100之间。
输出
输出最大的和
样例输入

5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5

样例输出

30

**解法一:**如果采用递归的方法,深度遍历每条路径,存在大量重复计算。时间复杂度为2n次方,超时。可将MaxSum(r,j)(r行j列的数最大路径保存起来),则时间复杂度缩短为n2。
代码

#include 
using namespace std;
const int 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() {
     
  cin >> n;
  for (int i = 1;i <= n;i++)
    for (int j = 1;j <= i;j++) {
     
      cin >> D[i][j];
      maxSum[i][j] = -1;//-1代表此点到底边最大和还没被计算出 
    }
  cout << MaxSum(1,1) << endl; 
  return 0;
} 

解法二

从n行开始往上一行一行向上递推。只需二维数组maxSum存储即可。

#include 
using namespace std;
const int MAX = 101;
int D[MAX][MAX];
int maxSum[MAX][MAX];
int n;
int main() {
     
  cin >> n;
  for (int i = 1;i <= n;i++)
    for (int j = 1;j <= i;j++) {
     
      cin >> D[i][j];
    }
  for (int i = 1;i <= n;i++)
    maxSum[n][i] = D[n][i]; //记录n行值 
  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[100]即可,存储一行的maxSum值就可以。

#include 
using namespace std;
int * maxSum,a[101][101];
int main() {
     
  int n;
  cin >> n;
  for (int i = 1;i <= n;i++)
    for (int j = 1;j <= i;j++)
      scanf("%d",&a[i][j]);
  maxSum = a[n];//maxSum指向第n行 
  for (int i = n - 1;i >= 1;i--)
    for (int j = 1;j <= i;j++)
      maxSum[j] = max(maxSum[j],maxSum[j + 1]) + a[i][j];
  cout << maxSum[1];
  return 0; 
}

你可能感兴趣的:(#,动态规划,动态规划)