抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

一方の笔记本

The only source of knowledge is experience.

2021年10月8日练习。

BJTU-ALGO 1002

记得我第一次用这个平台还是2020年的暑假小学期的时候,当时想按顺序做几道题,但是到这个题目就卡住了。思索很久也没有答案,正好最近在学动态规划,于是想着把这道题解出来。 ### 题目描述

在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧。在桥上有一些石子,青蛙很讨厌踩在这些石子上。由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数轴上的一串整点:\(0,1,\dots,L\)(其中\(L\)是桥的长度)。坐标为\(0\)的点表示桥的起点,坐标为\(L\)的点表示桥的终点。青蛙从桥的起点开始,不停的向终点方向跳跃。一次跳跃的距离是S到T之间的任意正整数(包括S,T)。当青蛙跳到或跳过坐标为L的点时,就算青蛙已经跳出了独木桥。 题目给出独木桥的长度\(L\),青蛙跳跃的距离范围\(S,T\),桥上石子的位置。你的任务是确定青蛙要想过河,最少需要踩到的石子数。

对于30%的数据,\(L \leq 10000\)

对于全部的数据,\(L \leq 10^9\)

输入数据

输入共包括三行。

第一行有一个正整数\(L(1≤L≤10^9)\), 表示独木桥的长度。

第二行有三个正整数\(S,T,M\), 分别表示青蛙一次跳跃的最小距离,最大距离及桥上石子的个数,其中\(1≤S≤T≤10,1≤M≤100\)

第三行有\(M\)个不同的正整数分别表示这\(M\)个石子在数轴上的位置(数据保证桥的起点和终点处没有石子)。所有相邻的整数之间用一个空格隔开。

输出数据

输出只包括一个整数,表示青蛙过河最少需要踩到的石子数。

样例输入

1
2
3
10
2 3 5
2 3 5 6 7

样例输出

1
2

题目分析

阅读题目可知只要跳过\(L\)即可,记到达某一位置\(i\)所需踩的最少的石头数记作\(\text{dp}[i]\),其中\(i \in [0, L-1+T]\),当前到达当前位置所需的代价与之前\(S\)\(T\)的位置有关。因此很容易写出状态转移方程\(\text{dp}[i]= \min(\text{dp}[i-j])\),其中\(S \leq i-j \leq T\)。再看题目中\(L\)的数据范围可知对于\(70\%\)的数据需要进行空间的压缩。由\(S\)\(T\)的范围,记\(\text{MOD}=\text{lcm}(1,...,10)\),则\(\text{MOD}=2520\)。之所以这样做的原因是要求出从任一位置\(i\)一定能前进的距离的最大值,也就是说可以任取\(i\)一定能从\(i\)跳至\((i+\text{MOD})\)处。由此可以对距离进行压缩,压缩至大约\(5 \times 10^5\)的范围内,可以使用动态规划。最终在区间\([L,L+T-1]\)的范围内找出最小值输出即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <bits/stdc++.h>
#define MOD 2520
using namespace std;
int main() {
int L;
cin >> L;
int S, T, M;
cin >> S >> T >> M;
vector<int> stones;
for (int i = 0; i < M; i++) {
int temp;
cin >> temp;
stones.emplace_back(temp);
}
sort(stones.begin(), stones.end(), less<int>());
vector<bool> compressed(MOD * 107);
vector<int> dis;
for (int i = 1; i < M; i++) {
dis.push_back((stones[i] - stones[i - 1]) % MOD);
}
stones[0] = stones[0] % MOD;
stones[0] += (stones[0] == 0 ? MOD : 0);
compressed[stones[0]] = true;
for (int i = 1; i < M; i++) {
stones[i] = stones[i - 1] + dis[i - 1];
compressed[stones[i]] = true;
}
L = stones[M - 1];
vector<int> dp(L + T + 1, 107);
dp[0] = 0;
for (int i = 1; i <= L + T; i++) {
for (int j = S; j <= T; j++) {
if (i - j >= 0) {
dp[i] = min(dp[i - j], dp[i]) + (compressed[i] == true ? 1 : 0);
}
}
}
int ans = 10e9;
for (int i = L; i < L + T; i++) {
ans = min(ans, dp[i]);
}
cout << ans << endl;
return 0;
}

评论