楼梯有n阶台阶,上楼可以一步上1阶,2阶,3阶,编程序计算共有多少种不同的走法?

时间:2025-04-16 07:14:27

 

 

题目:楼梯有n阶台阶,上楼可以一步上1阶,2阶,3阶,编程序计算共有多少种不同的走法

 

对于这样一个问题,

思路:设n阶台阶的走法数为f(n)。如果只有1个台阶,走法有1种(一步上1个台阶),即f(1)=1;如果有2个台阶,走法有2种(一种是上1阶,再上1阶,另一种是一步上2阶),即f(2)=2;如果有3个台阶,走法有4种(一种每次1阶,共一种;另一种是2+1,共两种;第三种是3,共1种),即f(3)=4;

当有n个台阶(n>3)时,我们缩小问题规模,可以这样想:最后是一步上1个台阶的话,之前上了n-1个台阶,走法为f(n-1)种,而最后是一步上2个台阶的话,之前上了n-2个台阶,走法为f(n-2)种,故而f(n)=f(n-1)+f(n-2)。列出的递归方程为:f(1)=1;f(2)=2;

f(3)=4;

if(n==1)

return 1;

else if(n==2)

return 2;

else if(n==3)

return 4;

else

return  f(n-1)+f(n-2)+f(n-3),n>3

最后一步可能是从第n-1阶往上走1阶、从n-2阶往上走2阶,或从第n-3阶往上走3阶。因此,抵达最后一阶的走法,其实就是抵达这最后三阶的方式的总和。

解决方法1:按照递归的思想;但运算时间很长

 

int countWays (int n)
{if (n<=0)
   return 0;
if (n==1)
   return 1;
else if(n==2)
   return 2;
else if(n==3)
   return 4;
else
  {
  return countWays(n-1)+countWays(n-2)+countWays(n-3);
 }
}   

 

 
解决方法2:采用动态规划的思想 优化,

当一个问题可以分解成若干重复的子问题时,运用动态规划的思想:

只需要将子问题求解一次,以后再遇到,直接调用,所以我们新建一个数组用于存储子问题的结果:
 
将数组元素初始为零,若为新的子问题,我们求解,并把结果赋给对应的数组元素;这样当我们再次遇到相同的子问题,就可以直接调用了。
 
int countWaysDP(int n, dp[])
 { if (n<0) 
    return 0; 
   if (n==0) 
   return dp[n]; 
   if (dp[n]>0) 
   return dp[n]; //如果大于0 说明这个子问题已经计算过,直接调用数组 
   else { 
   dp[n]=countWays[n-1,dp]+countWays[n-2,dp]+countWays[n-3,dp]; //否则 还需计算该数组 
   return dp[n]; } 
}
 
接下来贴上实际运行代码吧;
 
#include<iostream> 
using namespace std; 
const int MAX=1000; 
int countWays(int n) {
   if (n<0) 
     return 0; 
   if (n==0) 
      return 1; 
    else { 
  return countWays(n-1)+countWays(n-2)+countWays(n-3); 
  } 
} 

int countWaysDP(int n, int dp[]) {
    if (n<0) 
    return 0; 
    if (n==0) 
    return 1; 
    if (dp[n]>0) 
    return dp[n]; //如果大于0 说明这个子问题已经计算过,直接调用数组 
    else { 
    dp[n]=countWaysDP(n-1,dp)+countWaysDP(n-2,dp)+countWaysDP(n-3,dp); //否则 还需计算该数组 
    return dp[n]; } 
} 
   int main() { 
    int m[MAX]={0}; 
     // int m[MAX]; 
   for(int i=1;i<10;i++) 
   cout<<countWaysDP(i,m)<<endl; 
  }