码迷,mamicode.com
首页 > 其他好文 > 详细

20191026-跳台阶

时间:2019-10-26 23:07:02      阅读:122      评论:0      收藏:0      [点我收藏+]

标签:描述   unsigned   names   青蛙跳   lin   经典   sign   max   表示   

  • 斐波那契数列 - 矩阵算法\(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;
}

20191026-跳台阶

标签:描述   unsigned   names   青蛙跳   lin   经典   sign   max   表示   

原文地址:https://www.cnblogs.com/cbw052/p/11745662.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!