为了更好的阅读体检,可以查看我的算法学习博客
在线评测链接:P1045
题目内容
塔子哥是一个热爱户外运动的人,他周末经常约朋友一起登山。华光林山清水秀,景色宜人,让他感到非常愉悦。他喜欢在登山的过程中欣赏美景,感受大自然的魅力。同时,他也喜欢挑战自己,尝试攀登更高的山峰。
塔子哥登山时每一步可以选择向上爬一个台阶或者多个台阶,如果登山时选择的台阶不同,则为一种爬山方案。
塔子哥想知道,华光林的每座山各有多少种不同的爬山方案(输出结果对 10^9 +7 取模)。
输入描述
第一行,三个整数 N N N 、 P P P 和 K K K 分别代表山的个数 N N N ,塔子哥一次最高能爬的高度 P P P 以及塔子哥一次最多能跨越的台阶数 K K K 。
( 1 ≤ N ≤ 10 , 1 ≤ P ≤ 1 , 000 , 1 ≤ K ≤ 1 , 000 ) ( 1 \le N \le 10 , 1 \le P\le 1,000 , 1 \le K \le 1,000 ) (1≤N≤10,1≤P≤1,000,1≤K≤1,000)
接下来 N N N 行,每行的第一个整数 M i M_i Mi 表示第 i i i 座山一共有 M i M_i Mi 个台阶,接下来有 M i M_i Mi 个整数,分别表示每个台阶的高度 H j H_j Hj
( 1 ≤ M i ≤ 10 , 000 , 1 ≤ H j ≤ 1 , 000 ) ( 1 \le M_i \le 10,000, 1\le H_j \le 1,000 ) (1≤Mi≤10,000,1≤Hj≤1,000)。
输出描述
输出 N N N 行,每行一个整数,表示第 i i i 座山塔子哥可以选择的登山方案数目。
样例
输入
3 3 2
4 1 1 1 1
4 2 2 2 2
5 2 2 2 3 4
输出
5
1
0
备注
如果某一台阶 H j H_j Hj 的高度超过了塔子哥次能爬的高度 P P P , 那塔子哥就不会选择这爬座山, 登山方案数为 0 0 0 。
思路:线性DP
本题是斐波那契问题的变种,普通的爬楼梯问题中,每个台阶的高度都为 1 1 1,且一次要么向上爬一个台阶,要么向上爬两个台阶。
本题第 i i i 个台阶高度为 h i h_i hi ,一次最高能爬 P P P 的高度,一次最多能爬 K K K 个台阶。
定义 d p [ i ] dp[i] dp[i] 表示爬了 [ 1 , i ] [1, i] [1,i] 这 i i i 个楼梯的方案数,则考虑从 j ∈ [ 0 , i − 1 ] j \in [0, i-1] j∈[0,i−1] 这 i i i 种楼梯开始爬一次,到达 i i i 的总方案数。
这需要满足
i
−
j
≤
K
,
h
i
+
h
i
−
1
+
⋯
+
h
j
+
1
≤
P
i-j\leq K, h_i+h_{i-1}+\cdots+h_{j+1}\leq P
i−j≤K,hi+hi−1+⋯+hj+1≤P
在满足这种条件的
j
j
j 下,
d
p
[
i
]
=
∑
d
p
[
j
]
dp[i] = \sum\limits {dp[j]}
dp[i]=∑dp[j]
类似题目推荐
LeetCode
Codefun2000
代码
CPP
#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9 + 7;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, P, K;
cin >> n >> P >> K;
for (int turn = 0; turn < n; ++turn) {
int m; cin >> m;
vector<int> h(m + 1);
bool ok = true;
for (int i = 1; i <= m; ++i) {
cin >> h[i];
// 如果存在一个台阶的高度大于 P ,那无论如何也不可能爬完所有台阶
if (h[i] > P) {
ok = false;
}
}
if (!ok) {
cout << "0\n";
} else {
vector<int> dp(m + 1, 0);
dp[0] = 1;
for (int i = 1; i <= m; ++i) {
// height 表示从 j + 1 到 i 这些台阶的总高度
// 同时满足 i - j <= K
int height = h[i];
for (int j = i - 1; j >= max(i - K, 0) && height <= P; --j) {
dp[i] = (dp[i] + dp[j]) % MOD;
height += h[j];
}
}
cout << dp[m] << "\n";
}
}
return 0;
}
python
MOD = 10**9 + 7
n, P, K = map(int, input().split())
for turn in range(n):
h = list(map(int, input().split()))
m = h[0]
ok = True
for i in range(1, m + 1):
# 如果存在一个台阶的高度大于 P ,那无论如何也不可能爬完所有台阶
if h[i] > P:
ok = False
if not ok:
print(0)
else:
dp = [0] * (m + 1)
dp[0] = 1
for i in range(1, m + 1):
# height 表示从 j + 1 到 i 这些台阶的总高度
# 同时满足 i - j <= K
height = h[i]
for j in range(i - 1, max(i - K - 1, -1), -1):
if i - j > K:
break
dp[i] = (dp[i] + dp[j]) % MOD
if height + h[j] > P:
break
height += h[j]
print(dp[m])
Java
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int P = in.nextInt();
int K = in.nextInt();
for (int turn = 0; turn < n; ++turn) {
int m = in.nextInt();
int[] h = new int[m + 1];
boolean ok = true;
for (int i = 1; i <= m; ++i) {
h[i] = in.nextInt();
// 如果存在一个台阶的高度大于 P ,那无论如何也不可能爬完所有台阶
if (h[i] > P) {
ok = false;
}
}
if (!ok) {
System.out.println("0");
} else {
int MOD = 1000000007;
int[] dp = new int[m + 1];
dp[0] = 1;
for (int i = 1; i <= m; ++i) {
// height 表示从 j + 1 到 i 这些台阶的总高度
// 同时满足 i - j <= K
int height = h[i];
for (int j = i - 1; j >= Math.max(i - K, 0) && height <= P; --j) {
dp[i] = (dp[i] + dp[j]) % MOD;
height += h[j];
}
}
System.out.println(dp[m]);
}
}
}
}
Go
package main
import "fmt"
const MOD = 1000000007
func main() {
var n, P, K int
fmt.Scan(&n, &P, &K)
for turn := 0; turn < n; turn++ {
var m int
fmt.Scan(&m)
h := make([]int, m+1)
ok := true
for i := 1; i <= m; i++ {
fmt.Scan(&h[i])
// 如果存在一个台阶的高度大于 P ,那无论如何也不可能爬完所有台阶
if h[i] > P {
ok = false
}
}
if !ok {
fmt.Println(0)
} else {
dp := make([]int, m+1)
dp[0] = 1
for i := 1; i <= m; i++ {
// height 表示从 j + 1 到 i 这些台阶的总高度
// 同时满足 i - j <= K
height := h[i]
for j := i - 1; j >= max(i-K, 0) && height <= P; j-- {
dp[i] = (dp[i] + dp[j]) % MOD
height += h[j]
}
}
fmt.Println(dp[m])
}
}
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
Js
process.stdin.resume();
process.stdin.setEncoding('utf-8');
let input = '';
process.stdin.on('data', (data) => {
input += data;
return;
});
process.stdin.on('end', () => {
const lines = input.trim().split('\n');
const MOD = 1000000007;
let index = 0;
const [n, P, K] = lines[index++].trim().split(' ').map(Number);
for (let turn = 0; turn < n; turn++) {
const h = lines[index++].trim().split(' ').map(Number);
let m = h[0]
let ok = true;
for (let i = 1; i <= m; i++) {
if (h[i] > P) {
ok = false;
}
}
if (!ok) {
console.log('0');
} else {
const dp = new Array(m + 1).fill(0);
dp[0] = 1;
for (let i = 1; i <= m; i++) {
let height = h[i];
for (let j = i - 1; j >= Math.max(i - K, 0) && height <= P; j--) {
dp[i] = (dp[i] + dp[j]) % MOD;
height += h[j];
}
}
console.log(dp[m]);
}
}
});
题目内容均收集自互联网,如如若此项内容侵犯了原著者的合法权益,可联系我: (CSDN网站注册用户名: 塔子哥学算法) 进行删除。