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

来源:互联网 发布:linux 命令嵌套 编辑:程序博客网 时间:2024/04/27 14:46

题目:楼梯有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==0)   return 1;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;}






阅读全文
0 0
原创粉丝点击