动态编程:孩子上楼梯

时间:2018-11-04 22:22:16

标签: recursion dynamic-programming computer-science

我开始练习动态编程,只是无法解决这个问题:

问题:

一个孩子正在向上爬n级楼梯,可以一次跳1步,2步或3步。实施一种方法来计算孩子可以上楼梯的可能性。

破解编码访谈书的解决方案是这样的:

”“如果我们考虑到第n步的所有路径,我们可以将它们建立在前三个步骤的路径的基础上。我们可以通过以下任何一种方法到达第n个停靠点:

  • 转到第(n-1)步并跳1步
  • 转到第(n-2)步并跳2步
  • 转到第(n-3)步并跳3步”

因此要找到解决方案,只需将这些路径的数量加在一起即可!

那是让我迷失的地方!为什么这样的答案不是:先添加这些路径的数量,再添加3?由于如果您要执行步骤n-1或n-2或n-3,那么有3种方法可以执行第n步?我了解,如果您写下前4个基数案例的答案(假设n = 0返回1),您会看到类似斐波那契的模式。但是您可能也看不到它,所以很难。

然后they提出了以下代码:

public static int countWaysDP(int n, int[] map) {
if (n < 0) 
    return 0;
else if (n == 0)
    return 1;
else if (map[n] > -1)
    return map[n];
else {
    map[n] = countWaysDP(n - 1, map) + countWaysDP(n - 2, map) + countWaysDP(n - 3, map);
    return map[n]; }

}

第二个问题。当n == 0时如何返回1。即使我接受这一事实,如果在n == 1时返回0,我仍然找不到解决方法。

希望这很有道理。

谢谢

2 个答案:

答案 0 :(得分:0)

这是我如何把头缠在这个地方-

从书中-

  

在最后一跳,直到第 n 步,孩子可能已经   完成了单步,双步或三步跳。那就是最后   此举可能只是步骤 n-1 的单步跳跃,是两次   从步骤 n-2 跳一步,或从 n-3 跳三步。的   因此,到达最后一步的方法总数为   最后三个步骤中的每个步骤的数量

您正在正确考虑-

  

为什么不是这样的答案:添加这些路径的数量然后添加3?   由于如果您使用的是步骤n-1或n-2或n-3,则有3种方法   第n步?

这种基本情况的问题在于,仅当n> = 3时才适用。如果只有2个步骤,您显然不会加3。

让我们分解个别案例,了解这里的基本案例是什么。

n = 0

There are no stairs to climb.

Total number of ways = 0

n = 1

Total number of ways = 1StepHop from (n-1)
Number of ways to do 1StepHop from Step 0(n-1) = 1

Total number of ways = 1

n = 2

Total number of ways = 2StepHop from (n-2) + 1StepHop from (n-1)
Number of ways to do 2StepHop to reach Step 2 from Step 0(n-2) = 1
Number of ways to do 1StepHop to reach Step 2 from Step 1(n-1) = 1 (Previous answer for n=1) 

Total number of ways = 1 + 1 = 2

n = 3

Total number of ways = 3StepHop from (n-3) + 2StepHop from (n-2) + 1StepHop from (n-1)
Number of ways to do 3StepHop to reach Step 3 from Step 0(n-3) = 1
Number of ways to do 2StepHop to reach Step 3 from Step 1(n-2) = 2 (From previous answer for n = 2)
Number of ways to do 1StepHop to reach Step 3 from Step 2 = 1 (From previous answer for n=1) 

Total number of ways = 1 + 2 + 1 = 4

观察- 从上面可以看到,在每种情况下,我们都正确地考虑了最后一步。为 n-1 中的-> 1StepHop, n-2 中的 2StepHop分别添加一个 n-3 中的3StepHop。

现在查看代码,如果 n == 0 时返回 1 的情况有点违反直觉,因为我们已经看到答案应该是<如果 n == 0 ,则为strong> 0 。 -

public static int countWaysDP(int n, int[] map) {
if (n < 0) 
    return 0;
else if (n == 0) 
    return 1;  <------------- this case is counter-intuitive
else if (map[n] > -1)
    return map[n];
else {
    map[n] = countWaysDP(n - 1, map) + countWaysDP(n - 2, map) + countWaysDP(n - 3, map);
    return map[n];
}

从观察结果中,您可以看到 n == 0 的反直观情况实际上是说明最后一步的情况- n-1中的 1StepHop n-2 中的 2StepHop和 n-3 中的 3StepHop。

因此,仅在递归过程中使用 n == 0 大小写才有意义-仅当 n的初始值大于0 时才会发生。

对此问题的更完整解决方案可能是使用驱动程序方法,该方法可以在核心递归算法之外处理该情况-

int countWays(int n) {
    if (n <= 0 ) return 0;
    int[] map = new int[n+1];
    for(int i = 0; i<n+1; i++){
        map[i] = -1;
    }
    return countWaysDP(n, map);
}

希望这会有所帮助。

答案 1 :(得分:-1)

您可以在以下位置找到解决方案 https://github.com/CrispenGari/Triple-Step-Algorithim/blob/master/main.cpp

int count_Ways(int n){
   if(n<0){
      return 0;
   }else if(n==0){
      return 1;
   }else{
      return count_Ways(n-1) +count_Ways(n-2) + count_Ways(n-3);
  }
}
int main(){
   cout<<"Enter number of stairs: ";
   int n;
   cin>>n;
   cout<<"There are "<< count_Ways(n)<<"  possible ways the child can run up 
   thestairs."<<endl;
   return 0;
}