数塔就是由一堆数字组成的塔状结构,其中第一行1个数,第二行2个数,第三行3个数,依此类推。每个数都与下一层的左下与右下两个数相连接。这样从塔顶到塔底就可以有很多条路径可以走,现在需要求路径上的数字之和的最大值。
例如在上图中,5->8->12->10与5->3->16->11这两条路径上的数字之和都是35,是所有路径中的最大值。
结题思路:①递归实现 ②动态规划。
递归思路:从第一层开始,每下一层就该层的这个数据+判断选择左边还是右边,直到到最底层。
动态规划思路:从倒数第二层开始,将该层的数据与下一层较大的那个数据进行相加,更新数值,然后往上不断更新,直到到第一层,可以得出最大的数字。
总的来说,虽然可以从上向下计算数塔的最优路径和,但自底向上的动态规划通常更为常见和高效,因为它避免了重复计算,而且更容易理解和实现。如果性能不是关键问题,递归方法也是一个有效的解决方案,但需要特别关注优化。
递归代码如下:
#include <iostream>
#include <algorithm>
using namespace std;
int num[21][21];
int n;
int getmax(int i,int j){
if(i==n){
return num[i][j];
}
else{
return max(getmax(i+1,j),getmax(i+1,j+1))+num[i][j];
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
cin>>num[i][j];
}
}
cout<<getmax(1,1)<<endl;
return 0;
}
动态规划代码如下:
#include <iostream>
#include <vector>
using namespace std;
int findMaxPathSum(vector<vector<int>>& tower) {
int n = tower.size();
// 从倒数第二层开始向上计算最大路径和
for (int row = n - 2; row >= 0; row--) {
for (int i = 0; i <= row; i++) {
// 当前位置的最大路径和是当前位置的数字加上下一层左下和右下的较大值
tower[row][i] += max(tower[row + 1][i], tower[row + 1][i + 1]);
}
}
// 塔顶的最大路径和即为所求
return tower[0][0];
}
int main() {
vector<vector<int>> tower;
int n;
cin>>n;
for(int i=0;i<n;i++){
vector<int> temp;
int numtemp;
for(int j=0;j<=i;j++){
cin>>numtemp;
temp.push_back(numtemp);
}
tower.push_back(temp);
}
int maxPathSum = findMaxPathSum(tower);
cout << maxPathSum << endl;
return 0;
}