【发布时间】:2021-12-12 22:54:13
【问题描述】:
问题: 你正在爬楼梯。到达顶峰需要 n 步。 每次您可以跳 1 或 2 或 3 步。总共有多少种方法可以跳到顶部?
我的解释: 好吧,我正在考虑应用递归,因为我可以通过解决类似的子问题来找到解决方案,并且在这个过程中,会有许多重叠的子问题,所以我将排列数据结构来保存类似子问题的面额,这样我就不需要了解决相同的子问题两次。所以我使用的是自顶向下的DP方法。
我的疑问:
现在要构建解决方案,我需要一个基本案例,其中程序流程结束并返回到它的父节点(如果您将其可视化为一棵树)。所以我想的基本情况就像我在地板上时一样,在地面 0,所以我没有其他方法可以达到地面 0 状态,所以这是基本情况。
当 n=0 时,我应该返回 0 或 1,这是我的疑问吗?好吧,我已经编写了代码,所以当我返回 1 时代码工作,而不是在 n=0 时返回 0。那么为什么我在n=0的时候要返回1,这是什么原因呢?请帮忙!!!
我的代码:
#include <iostream>
using namespace std;
int climbing_ladders_topDown(int n, int k, int dp[]){
//Base Case
if(n==0){
return 1;
}
//LookUp
if(dp[n]!=0){
return dp[n];
}
//Recursive Case
int total_num_of_ways = 0;
for(int jumps=1;jumps<=k;jumps++){
if(n-jumps>=0){
total_num_of_ways += climbing_ladders_topDown(n-jumps,k,dp);
}
}
dp[n] = total_num_of_ways;
return dp[n];
}
int main() {
int num_of_stairs = 4;
int num_of_jumbs = 3;
int dp_arr[100] = {0};
cout<<climbing_ladders_topDown(num_of_stairs,num_of_jumbs,dp_arr);
return 0;
}
输出: 7
正确的代码流(感谢@appleapple):
#include <iostream>
using namespace std;
int climbing_ladders_topDown(int n, int k, int dp[]){
//Base Case
if(n==0){
return 0;
}
//LookUp
if(dp[n]!=0){
return dp[n];
}
//Recursive Case
int total_num_of_ways = 0;
for(int jumps=1;jumps<=k;jumps++){
if(n-jumps > 0){
total_num_of_ways += climbing_ladders_topDown(n-jumps,k,dp);
}
if(n-jumps == 0){ // have reach the end or ground 0, base so no more move possible in downward direction
total_num_of_ways += 1;
}
if(n-jumps < 0){ //we can't move to -ve state/underground, because it doesn't exist
total_num_of_ways += 0;
}
}
dp[n] = total_num_of_ways;
return dp[n];
}
int main() {
int num_of_stairs = 4;
int num_of_jumbs = 3;
int dp_arr[100] = {0};
cout<<climbing_ladders_topDown(num_of_stairs,num_of_jumbs,dp_arr);
return 0;
}
【问题讨论】:
-
因为
total_num_of_ways += climbing_ladders_topDown(n-jumps,k,dp);需要它是1。 -
嗯,这是一个合乎逻辑的答案,因为这是我通过试验 n 错误得出的结论。但我想知道,为什么在 n=0 时,dp[0] = 1?
-
是的
dp[0]应该是0。所以严格来说你的算法是错误的(对于n=0,它输出1) -
对不起,我编辑了。
-
只是一个注释,
dp[0]可以是1,如果你认为不移动是一种可能的方式。 (而0表示它需要至少移动 1 步)