【动态规划】走楼梯问题

走楼梯问题

问题:有一座高度是10级台阶的楼梯,从下往上走,每跨一步只能向上1级或者2级台阶。一共有多少种走法。(和铺瓷砖问题是一样的)

 

暴力枚举很简单,先选择可能性,再根据排列组合公式,记录。

但是显然阶乘是可能溢出的,且其时间复杂度为O(n^2)(这里加上了求阶乘的复杂度)

 

int N = 10;
    int M[2] = {1,2};
    int sum = 0;
    for (int i = 0; i <= 10/M[0]; ++i)
    {
 if ((N - i*M[0]) % M[1] != 0) continue;
 int n = (N - i*M[0]) / M[1] + i;
 // 这里是伪代码,!表示阶乘
 sum += n!/ (i!*(N - i)!)
    }

 

能不能把问题简单化呢?假设对台阶为10的求解是F(10),那么F(10)的最后一步是不是只能是停留在第8阶或者第9阶呢?

 

那么这个F(10)是不是相当于F(9)+F(8),注意不要理解错了,这里指的是最后一步,如果F(8)的时候你选择走一步,那么这个问题应该归类于F(9)

 

那么我们递推会发现,这是一个数学问题

   F(n)=F(n-1)+F(n-2)
   F(10)=F(9)+F(8)
   F(9)=F(8)+F(7)
   F(8)=F(7)+F(6)
   ...
   F(2)=F(1)+F(0)  F(2)=2
   F(1)=F(0)       F(1)=1
   F(0)=1

 

求F(n),显然这是一个栈底已知的递归算法,那么我们自下而上的看,只需一个简单的循环求和就行了

int Fi_1=0 ,Fi_2=0;
for (int i=1;i<=n;i++)
{
   if(i=1) Fi_2=1;
   if(i=2) Fi_1=2;
   int Fi=Fi_1+Fi_2;
   Fi_2 = Fi_1;
   Fi_1 = Fi;
}
return Fi_1

 

思路写出来后,小小的优化一下,能手动算的,咱自个儿算算

unsigned long long F(int n)
{
    if (n < 0)
 return 0;
    if (n == 0)
 return 1;
    if (0 < n && n <= 3)
 return n;
    unsigned long long Fi_1 = 3;
    unsigned long long Fi_2 = 2;
    unsigned long long Fi = 0;
    for (int i = 4; i <= n; ++i)
    {
        Fi = Fi_1 + Fi_2;
        Fi_2 = Fi_1;
        Fi_1 = Fi;
    }
    return Fi;
}

 

这个算法的时间复杂度变成O(n),当然溢出问题还是没有解决,暂时只能通过限制输入

 

如果每一步能跨出m种可能,显然暴力算法时间复杂度在选择可能性这一步就爆炸了,指数级算法是不可取的。那么这个动态规划算法仅需增加m-2个变量即可完美胜任。

 

那么回过来想

 

动态规划是什么

 

把多阶段过程转化为一系列单阶段问题,利用各阶段之间的关系,逐个求解,解决这类过程优化问题的方法,也就是推导出上面F(n)=F(n-1)+F(n-2)的思路。

 

 

 

 

 

点击关注,持续推送质量好文;如有不当,欢迎指出;转载请注明出处。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值