题目描述
一天一只顽猴想去从山脚爬到山顶,途中经过一个有个N个台阶的阶梯,但是这猴子有一个习惯:
每一次只能跳1步或跳3步,试问猴子通过这个阶梯有多少种不同的跳跃方式?
输入描述
输入只有一个整数N(0<N<=50)此阶梯有多少个台阶。
输出描述
输出有多少种跳跃方式(解决方案数)。
用例
输入 | 50 |
输出 | 122106097 |
说明 | 无 |
输入 | 3 |
输出 | 2 |
说明 | 无 |
题目解析
这题是一道经典的分治算法题、以及动态规划基础题。
这题既可以使用分治递归来自顶向下地求解,也可以使用动态规划递推地自底向上求解。
但是动态规划的效率更高。
这题和fibnaci数列很像,递归公式如下:
- jump(1) = 1
- jump(2) = 1
- jump(3) = 2
- jump(n) = jump(n-1) + jump(n-3), n>3
状态转移方程如下:
- dp[0] = 0
- dp[1] = 1
- dp[2] = 1
- dp[3] = 2
- dp[i] = dp[i-1] + dp[i-3], i>3
上面递归公式和状态转移方程的规律发现如下
台阶数 | 跳跃方式 | 几种跳跃方式 |
1 | 1 | 1 |
2 | 11 | 1 |
3 |
111 3 |
2 |
4 |
1111 13 31 |
3 |
5 |
11111 113 131 311 |
4 |
6 |
111111 1113 1131 1311 3111 33 |
6 |
7 |
1111111 11113 11131 11311 13111 31111 133 313 331 |
9 |
Java算法源码
分治递归求解(带缓存优化)
import java.util.Arrays;
import java.util.Scanner;
public class Main {
static int[] cache = new int[51];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
Arrays.fill(cache, -1);
cache[0] = 0;
cache[1] = 1;
cache[2] = 1;
cache[3] = 2;
System.out.println(recursive(n));
}
public static int recursive(int n) {
if (cache[n] != -1) return cache[n];
cache[n] = recursive(n - 1) + recursive(n - 3);
return cache[n];
}
}
动态规划算法求解
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
System.out.println(getResult(n));
}
public static int getResult(int n) {
int[] dp = new int[n + 1];
if (n >= 1) dp[1] = 1;
if (n >= 2) dp[2] = 1;
if (n >= 3) dp[3] = 2;
for (int i = 4; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 3];
}
return dp[n];
}
}
JS算法源码
分治递归求解(带缓存优化)
/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.on("line", (line) => {
const n = parseInt(line);
console.log(recursive(n));
});
const cache = [0, 1, 1, 2];
function recursive(n) {
if (cache[n]) return cache[n]; // n > 0
cache[n] = recursive(n - 1) + recursive(n - 3);
return cache[n];
}
动态规划算法求解
/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.on("line", (line) => {
const n = parseInt(line);
console.log(getResult(n));
});
function getResult(n) {
const dp = new Array(n + 1).fill(0);
if (n >= 1) dp[1] = 1;
if (n >= 2) dp[2] = 1;
if (n >= 3) dp[3] = 2;
for (let i = 4; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 3];
}
return dp[n];
}
Python算法源码
分治递归求解(带缓存优化)
# 输入获取
n = int(input())
cache = [-1] * 51
cache[0] = 0
cache[1] = 1
cache[2] = 1
cache[3] = 2
# 算法入口
def recursive(n):
if cache[n] != -1:
return cache[n]
cache[n] = recursive(n - 1) + recursive(n - 3)
return cache[n]
# 调用算法
print(recursive(n))
动态规划算法求解
# 输入获取
n = int(input())
# 算法入口
def getResult():
dp = [0]*(n+1)
if n >= 1:
dp[1] = 1
if n >= 2:
dp[2] = 1
if n >= 3:
dp[3] = 2
for i in range(4, n+1):
dp[i] = dp[i-1] + dp[i-3]
return dp[n]
# 调用算法
print(getResult())
免责声明:
1、IT资源小站为非营利性网站,全站所有资料仅供网友个人学习使用,禁止商用
2、本站所有文档、视频、书籍等资料均由网友分享,本站只负责收集不承担任何技术及版权问题
3、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除下载链接并致以最深的歉意
4、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
5、一经注册为本站会员,一律视为同意网站规定,本站管理员及版主有权禁止违规用户
6、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和IT资源小站的同意
7、IT资源小站管理员和版主有权不事先通知发贴者而删除本文
评论0