湖南大学信息科学与工程学院第15届生涯规划节周末夜校之C++讲座
(Date:20201205,面向2020级大一新生)
Description
给定一个数塔,如下图所示。在此数塔中,从顶部出发,在每一节点可以选择走左下或右下,一直走到底层。请找出一条路径,使路径上的数值和最大。
Input
输入时第一行一个整数n,表示该数塔的行数,其余n行表示该塔每行的数值
Output
最大路径上的数值之和
Sample Input
5
9
12 15
10 6 8
2 18 9 5
19 7 10 4 16
Sample Output
59
递归问题的一般方法
1、找到递归开始状态,即递归入口;
2、调用递归函数;
3、判断递归参数合法性,制定“由错误导致的”递归终止条件;
4、为合法的参数执行运算操作;
5、找到递归边界并判断,制定“由递归边界导致的”递归终止条件;
6、确定下一步的递归方向,用更新的参数调用递归;
7、函数返回上一层递归前,还原在本层递归中改变的参数。
本题思路
1、找到递归开始状态,即递归入口:arr作为数塔的存储位置,从塔顶开始计算路径累加和,即arr[1][1]。
2、调用递归函数:递归函数传入当前塔层数depth,当前搜索该层的第几个数字位pos,和塔总层数n。
3、判断递归参数合法性,制定“由错误导致的”递归终止条件:如果pos>n,说明当前搜索位置大于本层元素的数量,直接错误返回。
4、为合法的参数执行运算操作:计算路径上的累加和,加上当前搜索塔元素的值。
5、找到递归边界并判断,制定“由递归边界导致的”递归终止条件:如果depth和塔深度相等,就说明已经到了塔底,此时将路径的累加和与当前的最大值比较。如果当前路径累加高于当前最大值,则最大值设置为当前路径。
6、确定下一步的递归方向,用更新的参数调用递归:下一层搜索时,层数+1,搜索位置为pos(向左)或pos+1(向右)。
7、函数返回上一层递归前,还原在本层递归中改变的参数:本层中对于result,即当前路径的累加和进行了更新,因此函数返回前减去当前位置的元素,再退回上一层递归(就好像没有访问过本层一样)。
参考代码和注释
#include<iostream>
using namespace std;
int result=0;
int cur_max=-1;
int arr[101][101];
int n;
void search(int depth, int pos,int n)
{
if(pos>depth) //递归终止条件之一:当前行位置不可以超过深度(第n层有n个元素)
return;
result+=arr[depth][pos]; //函数操作,路径大小值加上本层的搜索节点
if(depth==n) //递归终止条件之二:已经递归到最后一层
{
if(result>cur_max) //如果当前的结果大于已有的最大路径,即更新
cur_max=result;
result-=arr[depth][pos]; //否则在返回前需要减去本次加上的节点,回到上一层,当做本层还未递归,即,复原
return;
}
search(depth+1,pos,n); //下一轮递归的深度+1,位置可以往左(不变)或往右(+1)
search(depth+1,pos+1,n);
result-=arr[depth][pos]; //在该函数返回前,需要复原状态。
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
cin>>arr[i][j];
}
search(1,1,n); //从数塔的第一个元素开始搜索,即搜索位置为第1层的第1个元素
cout<<cur_max;
return 0;
}
拓展阅读
搜索:递归和动态规划(dp)的区别与联系