zoukankan      html  css  js  c++  java
  • 20191026-跳台阶

    • 斐波那契数列 - 矩阵算法(O(lgn)) - 待补充
    • 跳台阶 - 经典问题
      • 递归 - basic解法,浪费栈空间
      • 动态规划 - 常规解法,转移方程可以有很多变化
      • 打表 - 按照转移方程提前计算
      • 注意:台阶数很多的时候,需要手写大数加法
    • 变态跳台阶/观察法
    • 跳石板/动态规划
    • 爬楼梯/大数跳台阶
    • 爬楼梯2/大数加法

    变态跳台阶

    一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法 (2^{n-1})

    思路

    • 思路1

      • 青蛙一次可以跳1~n之间的台阶数,考虑如下情况
        • 青蛙一次跳n阶,则1~n-1的所有台阶均不经过
        • 青蛙第一次跳n-1阶,第二次跳1阶,等价于仅选中n-1阶
      • 所以,观察可得,每种跳台阶方案都对应了1~n-1中的唯一一组选择
        • 1~n-1共n-1级台阶,每级台阶都有选or不选两种情况
        • 总的跳法数目为(2^{n-1})
    • 思路2

      • (f(n-1)=2^{n-2}) 数学归纳法
      • (f(n)=1+f(n-1)+f(n-2)+f(n-3)+...+f(2)+f(1))
      • (f(n)=2^{n-1})

    跳石板

    小易来到了一条石板路前,每块石板上从1挨着编号为:1、2、3.......
    这条石板路要根据特殊的规则才能前进:对于小易当前所在的编号为K的 石板,小易单次只能往前跳K的一个约数(不含1和K)步,即跳到K+X(X为K的一个非1和本身的约数)的位置。 小易当前处在编号为N的石板,他想跳到编号恰好为M的石板去,小易想知道最少需要跳跃几次可以到达。
    例如:
    N = 4,M = 24:
    4->6->8->12->18->24
    于是小易最少需要跳跃5次,就可以从4号石板跳到24号石板

    思路

    状态转移

    (steps[i+j]=min(steps[i]+1,steps[i+j]))

    (steps[i+i/j]=min(steps[i]+1,steps[i+i/j]))

    注意这里对约数的处理很巧妙,j from 2 to i^(1/2)

    代码

    #include<iostream>
    #include<climits> //INT_MAX,INT_MIN等
    #include<cmath> //min,max等函数
    #include<vector>
    using namespace std;
    
    int main(){
        int N,M;
        while(cin>>N>>M){
            vector<int> steps(M+1,INT_MAX);
            steps[N]=0;
            for(int i=N;i<=M;i++){
                if(steps[i]==INT_MAX)
                    continue;
                //快速计算i的约数
                for(int j=2;(j*j)<=i;j++){
                    if(i%j==0){
                        if(i+j<=M){
                            steps[i+j]=min(steps[i]+1,steps[i+j]);
                        }
                        if(i+i/j<=M){
                            steps[i+i/j]=min(steps[i]+1,steps[i+i/j]);
                        }
                    }
                }
            }
            if(steps[M]==INT_MAX){
                steps[M]=-1;
            }
            cout<<steps[M]<<endl;
        }
    }
    

    爬楼梯

    题目描述

    在你面前有一个n阶的楼梯,你一步只能上1阶或2阶。
    请问计算出你可以采用多少种不同的方式爬完这个楼梯。

    输入描述:

    一个正整数n(n<=100),表示这个楼梯一共有多少阶
    

    输出描述:

    一个正整数,表示有多少种不同的方式爬完这个楼梯
    

    思路

    不愧是校招题目,大坑在数据范围,unsigned long long不够用,需要手写大数加法

    代码

    #include<iostream>
    using namespace std;
    
    int main(){
        int n;
        cin>>n;
        int num[103][30]={0};//二维数组的初始化,int数组进行大数加法
        num[1][29]=1;
        num[2][29]=2;
        for(int i=3;i<=100;i++){
            //从低位向高位计算
            int carry=0;//进位初始设置为0
            for(int j=29;j>=0;j--){
                num[i][j]=(num[i-1][j]+num[i-2][j]+carry)%10;
                carry=(num[i-1][j]+num[i-2][j]+carry)/10;
            }
        }
        int j=0;
        while(num[n][j]==0)
            j++;
        for(int i=j;i<30;i++)
            cout<<num[n][i];
        cout<<endl;
    }
    

    爬楼梯2

    题目描述

    在你面前有一个n阶的楼梯(n>=100且n<500),你一步只能上1阶或3阶。
    请问计算出你可以采用多少种不同的方式爬完这个楼梯(到最后一层为爬完)。

    输入描述:

    一个正整数,表示这个楼梯一共有多少阶
    

    输出描述:

    一个正整数,表示有多少种不同的方式爬完这个楼梯
    

    代码

    #include<iostream>
    
    using namespace std;
    
    int len=99;
    
    int num[501][100];//这里大数的位数会很高,用len+1表示
    
    int main(){
        num[1][len]=1;
        num[2][len]=1;
        num[3][len]=2;
        for(int i=4;i<500;i++){
            int carry=0;
            for(int j=len;j>=0;j--){
                num[i][j]=(num[i-1][j]+num[i-3][j]+carry)%10;
                carry=(num[i-1][j]+num[i-3][j]+carry)/10;
            }
        }
        int n;
        cin>>n;
        int j=0;
        while(num[n][j]==0)
            j++;
        for(;j<=len;j++){
            cout<<num[n][j];
        }
        cout<<endl;
    }
    
  • 相关阅读:
    Luogu 1080 【NOIP2012】国王游戏 (贪心,高精度)
    Luogu 1314 【NOIP2011】聪明的质检员 (二分)
    Luogu 1315 【NOIP2011】观光公交 (贪心)
    Luogu 1312 【NOIP2011】玛雅游戏 (搜索)
    Luogu 1525 【NOIP2010】关押罪犯 (贪心,并查集)
    Luogu 1514 引水入城 (搜索,动态规划)
    UVA 1394 And Then There Was One / Gym 101415A And Then There Was One / UVAlive 3882 And Then There Was One / POJ 3517 And Then There Was One / Aizu 1275 And Then There Was One (动态规划,思维题)
    Luogu 1437 [HNOI2004]敲砖块 (动态规划)
    Luogu 1941 【NOIP2014】飞扬的小鸟 (动态规划)
    HDU 1176 免费馅饼 (动态规划)
  • 原文地址:https://www.cnblogs.com/cbw052/p/11745662.html
Copyright © 2011-2022 走看看