任务描述
本关任务:一个楼梯共有n(n<10000)阶台阶,规定每步可以迈1阶、2阶或3阶。从1阶到第n阶,一共可以有多少种不同的迈法。(用两种方法:1:普通的递归 2:动态规划)
相关知识
为了完成本关任务,你需要掌握:1.如何将待求解的问题分解成若干个相互联系的子问题;2.如何将一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解;
动态规划
动态规划( dynamic programming )算法是解决多阶段决策过程最优化问题的一种常用方法,难度比较大,技巧性也很强。利用动态规划算法,可以优雅而高效地解决很多贪婪算法或分治算法不能解决的问题。动态规划算法的基本思想是:将待求解的问题分解成若干个相互联系的子问题,先求解子问题,然后从这些子问题的解得到原问题的解;对于重复出现的子问题,只在第一次遇到的时候对它进行求解,并把答案保存起来,让以后再次遇到时直接引用答案,不必重新求解。动态规划算法将问题的解决方案视为一系列决策的结果,与贪婪算法不同的是,在贪婪算法中,每采用一次贪婪准则,便做出一个不可撤回的决策;而在动态规划算法中,还要考察每个最优决策序列中是否包含一个最优决策子序列,即问题是否具有最优子结构性质。
动态规划算法的有效性依赖于待求解问题本身具有的两个重要性质:最优子结构性质和子问题重叠性质。
1 、最优子结构性质。如果问题的最优解所包含的子问题的解也是最优的,我们就称该问题具有最优子结构性质(即满足最优化原理)。最优子结构性质为动态规划算法解决问题提供了重要线索。
2 、子问题重叠性质。子问题重叠性质是指在用递归算法自顶向下对问题进行求解时,每次产生的子问题并不总是新问题,有些子问题会被重复计算多次。动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只计算一次,然后将其计算结果保存在一个表格中,当再次需要计算已经计算过的子问题时,只是在表格中简单地查看一下结果,从而获得较高的解题效率。
当我们已经确定待解决的问题需要用动态规划算法求解时,通常可以按照以下步骤设计动态规划算法:
1 、分析问题的最优解,找出最优解的性质,并刻画其结构特征;
2 、递归地定义最优值;
3 、采用自底向上的方式计算问题的最优值;
4 、根据计算最优值时得到的信息,构造最优解。
测试说明
平台会对你编写的代码进行测试:
测试输入:5
预期输出:13
测试输入:10
预期输出:274
提示:
动态规划可以用数组储存数据,用循环完成递归的步骤
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
//获得输入的台阶数
Scanner input = new Scanner(System.in);
int n = input.nextInt();
//调用方法
long sum1=climbingStairs1(n);
System.out.println(sum1);
//long sum2 =climbingStairs2(n);
//System.out.println(sum2);
}
/**
* 普通地递归,自顶向下求解
* @param n 台阶数
* @return 迈法总数
*/
public static long climbingStairs1(int n) {
//递归终止条件
if(n==1){
return 1;
}
if(n==2){
return 2;
}
if(n==3){
return 4;
}
//递归调用
return climbingStairs1(n-1)+climbingStairs1(n-2)+climbingStairs1(n-3);
}
/**
* 动态规划,自底向上求解
* @param n 台阶数
* @return 迈法总数
*/
public static long climbingStairs2(int n) {
int[] dp =new int[n+3];
dp[1]=1;
dp[2]=2;
dp[3]=4;
for(int i=4;i<=n;i++){
dp[i]=dp[i-1]+dp[i-2]+dp[i-3];
}
return dp[n];
}
}