问题描述
Please implement solution for Number Tower with any programming language and analyze its time complexity.
翻译
数塔问题是一个经典的动态规划问题,它描述了一个由数字组成的三角形结构,要求从顶部开始向下走,每次只能走到相邻的位置,最终到达底部,使得经过的数字之和最大。数塔问题可以用一个二维数组来表示,其中第i行有i个元素,表示第i层的数字。例如:
9
12 15
10 6 8
2 18 9 5
16 12 18 10 8
数塔问题的一个可能的最优路径是:9 -> 15 -> 8 -> 9 -> 18,其和为59。
思路
首先将dp数组初始化为0,将最下方一排初始化为 数塔最低一排的数字
然后自底向上递归,每次和左右两个数相加,取最大值,一直到顶部为止
dp[i][j]=max(dp[i][j],dp[i][j+1])+a[i][j]
(此文代码是为了回溯才没用上述状态方程,都但是思路一致)
代码
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string>
#include <algorithm>
#include <stdlib.h>
using namespace std;
const int N = 100;
/*
* 7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
30
*/
void trackBack(int track[][N], int tow[][N], int n)
{
int i = 1,j=1;
while (i <= n)
{
printf("%d->", tow[i][j]);
if (track[i][j] == 1)
;
else
j++;
i++;
}
}
int sumMax(int tow[][N], int n)
{
int ans[N][N] = { 0 };
int track[N][N];
for (int i = 1; i <= n; i++)
ans[n][i] = tow[n][i];//答案最后一层赋值为塔的最后一层,往上赋值为左右最大值与中间相加
for (int i = n - 1; i >= 1; i--)
for (int j = 1; j <= i; j++)
if (ans[i + 1][j] > ans[i + 1][j+1])
{
track[i][j] = 1;//左边
ans[i][j] = ans[i + 1][j] + tow[i][j];
}
else
{
track[i][j] = 2;//右边
ans[i][j] = ans[i + 1][j+1]+tow[i][j];
}
trackBack(track, tow, n);
return ans[1][1];
}
int main()
{
int n;
cout << "Please enter the The number of floors of the Number tower:" << endl;
int towel[N][N] = { 0 };
cin >> n;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= i; j++)
cin >> towel[i][j];
int max=sumMax(towel, n);
cout << "The MaxSum is " << max;
return 0;
}
测试案例
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
运行结果
时间复杂度分析
速记
dp[i][j]=max(dp[i][j],dp[i][j+1])+a[i][j]
回溯函数留意一下
同时内层循环参数留意一下