动态规划走楼梯问题

有一条楼梯,总共有9级阶梯,从地面上出发,如果每次可以走3级,4级或6级楼梯,问共有几种方案可以走到?

解决方案一:

第一个方法比较简单,很容易想到,就是用深度搜索,我们可以反过来,把情况看出从第9层阶梯走到路面,把所有可以出现的情况都列出来,然后判断是否能到达第9级阶梯,如果可以,就把方案数加一。

代码如下:

public class DPStair {

    static int count=0; //计算F(n)被调用了计次
    static int F(int n)
    {
        count++;
        if(n==0) return 1;         //n等于0,恰好到达9层阶梯
        if(n<0) return 0;
        return F(n-3)+F(n-4)+F(n-6);  //深搜,走3级,4级,6级能到达目的地的次数相加
    }

    public static void main(String[] args) {
        int n=9;
        System.out.println(F(n)+" count="+count);
    }
}

但如果现在要求得是能到底第90级阶梯的次数呢,我用上面深搜的方法,程序大概运行了一分钟左右才得出结果,这才求90级阶梯,速度太慢了。下面用动态规划优化下这个程序。

我们把这个问题分解下,走到第9级楼梯的方案可以看出从第8级楼梯走到第9级楼梯的方案加上第7级楼梯走到第9级楼梯的方案······

走到第8级楼梯的方案可以看出从第7级楼梯走到第8级楼梯的方案加上第6级楼梯走到第8级楼梯的方案······

这样类推下来,我们可以看到,用上面的深搜方法,仔细观察下,计算第第7级楼梯走到第8级楼梯的方案 和 计算第第7级楼梯走到第9级楼梯的方案 这两次计算的重复了,也就是说我们重复计算了两次走到第7级楼梯的方案,所以我们考虑下把走到某一级楼梯的方案数记录下来,如果再次需要用到走到该级楼梯方案数的时候,就不需要再去计算,把之前记录下来的方案数取出来用就行了,代码如下:

public class Stairs {
    static int count=0;
    static int[] Sum;     //用来记录走到某级楼梯的方案数
    static int F(int n)
    {
        count++;
        if(n==0) return 1;
        if(n<0) return 0;
        if(Sum[n]!=-1) return Sum[n];     //如果走到该级楼梯的方案数已经存在,直接取用就行,不用继续深搜计算走到该级楼梯的方案数
        Sum[n]=F(n-3)+F(n-4)+F(n-6); //如果没有记录,计算能走到该级楼梯的方案数
        return Sum[n];   //返回方案数
    }

    public static void main(String[] args) {
        int n=90;
        Sum=new int[n+1];
        for(int i=0;i<=n;i++) Sum[i]=-1;   //初始化-1,表示走到该级楼梯的方案数还没有记录
        System.out.println(F(n)+" count="+count);
    }

}

但n=90的时候,我们运行程序,结果是秒出的,输出count的值是262,而用上面那个没有优化深搜的程序,count输出是负数,也就是已经超出了Int的最大值范围,可以比较出来优化的效果还是比较明显的

时间: 2024-11-05 02:21:19

动态规划走楼梯问题的相关文章

走楼梯(walk) 解题报告

走楼梯(walk) 题意 给一个长为\(n(1\le n\le 10^5)\)序列\(\{a\}\),每次从中间挖掉\([l,r]\),然后询问最长上升子序列,强制在线. 有一档分是30000和离线,然后考试的时候一直在莫队,发现就是不会删除....想到了离线树套树又懒得打.后来发现莫队只需要实现撤回就可以了..太菜了窝 然后我居然一直没想分块(大雾) 这里直接放原题解了,说的十分详细 年后就去刷ynoi(flag Code: #include <cstdio> #include <cm

动态规划-爬楼梯问题

其实我一直分不清楚动态规划和分治,递归之间的区别与联系...<( ̄3 ̄)> 三者之间应该是有点关系的吧 网上说: 1. 什么是动态规划?         和分治法一样,动态规划(dynamicprogramming)是通过组合子问题而解决整个问题的解.         分治法是将问题划分成一些独立的子问题,递归地求解各子问题,然后合并子问题的解.         动态规划适用于子问题不是独立的情况,也就是各子问题包含公共的子子问题.         此时,分治法会做许多不必要的工作,即重复地求

斐波那契走楼梯

题目描述 NowCoder小时候走路喜欢蹦蹦跳跳,他最喜欢在楼梯上跳来跳去.但年幼的他一次只能走上一阶或者一下子蹦上两阶.现在一共有N阶台阶,请你计算一下NowCoder从第0阶到第N阶共有几种走法. 输入描述: 输入包括多组数据.每组数据包括一个整数n, (1≤n≤90). 输出描述: 对应每个输入包括一个输出.为redraiment到达第n阶不同走法的数量. 输入例子: 12 输出例子: 12 #include <iostream> using namespace std ; int ma

走楼梯

1.每次可以走1步,或两步,求走n级台阶的方案个数 分析,其实就是斐波那契数列,无论怎么走,最后一步要么走1级,要么走2级,所以n级方案等于n-1级和n-2级方案之和 import java.util.HashMap; public class WalkStairs { // 上n级台阶 public static int walkStairs(int n) { if (n == 1) return 1; else if (n == 2) return 2; return walkStairs(

走楼梯算法

首先,我们来看下下面这栋楼梯: 一共四层,我们规定"一个人爬楼梯,一步可以迈一级,二级台阶,如果楼梯有N级,要求编写程序,求总共有多少种走法",接下来我们统计下这四层,每层的走法: 从这个简短的统计中,我们可以发现一个规律(如果觉得还看不出,可以再多几阶楼梯),从第三阶梯开始,走法就是第一阶梯走法和第二阶梯走法之和,第四阶梯走法是第三阶梯和第二阶梯走法之和,所以,我们可以得到如下如下公式: 由此可知,此处应用递归算法. 而第一阶梯和第二阶梯这样无规律的数字,我们可以将他定量表示,由此,

走楼梯升级版(原创题目)

灵感来源:http://www.cnblogs.com/TheRoadToTheGold/p/7476715.html Description tot 阶楼梯,每次可以往上跳 1—n 步,往下跳 1——m 步 而且在往下跳的时候只能踩在往上跳时踩过的格子. 现在 xxy 在楼梯上乱跳,想问她跳到楼梯顶上最后又跳回楼梯下面的方案数 mod233333333. 注意:xxy 只能一直向上跳,跳到楼梯最上面,然后再往下跳,跳回楼梯最底下. Input 一行 3 个整数 tot,n,m Output 方

动态规划--上楼梯

题目:假设你需要进入一个房间,但是房间在楼上,你需要走完n阶台阶,才能到楼上,如果你一次性可以走1.2或3个台阶,可以计算出你一共有多少种方案去走完所有的台阶进入房间呢? 解题思路:定义一个状态函数f(n)用来表示如果要走n阶台阶一共可以有方案数量,则f(n)=f(n-1)+f(n-2)+f(n-3).当n=1时只有一中方案,当n=2时有两种方案(1,1;2),当n=3时有4种方案(1,1,1;1,2;2,1;3),依次类推. 具体算法(Java版) 1 /** 2 * 计算n个台阶一共有多少中

走楼梯2

Description ?One steps through integer points of the straight line. The length of a step must be nonnegative and can be by one bigger than, equal to, or by one smaller than the length of the previous step. ?What is the minimum number of steps in orde

动态规划--LintCode简单题

1.爬楼梯 题目:假设你正在爬楼梯,需要n步你才能到达顶部.但每次你只能爬一步或者两步,你能有多少种不同的方法爬到楼顶部? 分析:一次只能爬一步或者两步,所以走i步可由走i-1步的方法数和走i-2步的方法数相加获得: 设dp[i]为走i步的方法数目,则dp[i]=dp[i-1]+dp[i-2]; 注意:边界问题,由上面的方程可知道 i 由2开始,且dp[0]=dp[1]=1; 代码: class Solution {public:    /**     dp[i]=dp[i-1]+dp[i-2]