Files
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

73 lines
2.9 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <bits/stdc++.h>
using namespace std;
const int N = 10020; // 定义一个足够大的数组空间
// 全局变量声明
int L, S, T, m; // L:桥长度, S:最小跳跃距离, T:最大跳跃距离, m:石子数量
int stones[N]; // 存储石子的位置
int w[N]; // 记录每个位置是否有石子(离散化后)
int f[N]; // dp数组,f[i]表示跳到位置i最少需要踩的石子数
int main() {
// 读入基本数据
cin >> L >> S >> T >> m;
// 特殊情况处理:当最小跳跃距离等于最大跳跃距离时
// 此时青蛙只能跳固定距离S
if (S == T) {
int res = 0;
while (m--) {
int x;
cin >> x;
// 如果石子位置是S的倍数,青蛙一定会踩到
if (x % S == 0)
res++;
}
printf("%d\n", res);
return 0;
}
// 读入所有石子的位置
for (int i = 0; i < m; i++)
cin >> stones[i];
sort(stones, stones + m); // 将石子位置从小到大排序
// 核心算法:离散化处理
int last = 0, k = 0; // last:上一个处理的位置, k:离散化后的新位置
for (int i = 0; i < m; i++) {
// 重要优化:基于数论的优化
// 当两个相邻石子距离过大时,中间的空隙可以被压缩
// 91是基于(p-1)(q-1)-1+20得来,其中p=10,q=9
// 这个优化基于:当两点距离大于91时,一定可以通过组合S和T的跳法到达
// 核心:桥太长,无法遍历,但有一个突破口,就是石子数量有限
// 如何利用这点呢?使用上面的定理,我们知道,间距太大的间隙可以被压缩,只有大于91的空隙,就可以压缩
// 如何压缩,压缩完是什么样的东西呢?
// 就是把无意义的没有石子的位置移除掉!无意义的是指肯定能通过ST踩到的并且无石子的位置
// 有意义的就是可能踩到也可能踩不到的位置,这些位置保留下来,无意义的干掉就行了。
// 下面的循环,枚举的是两个相邻石子之间的空位。
for (int j = 0; j < min(stones[i] - last, 91); j++)
w[++k] = 0; // 在新的离散化空间中标记无石子的位置
w[k] = 1; // 标记有石子的位置
last = stones[i];
}
// 动态规划初始化
memset(f, 0x3f, sizeof(f)); // 预求最大先设最小
f[0] = 0; // 注意边界的初始化,思考现实含义:位置 0最少需要踩的石子数为 0
// 动态规划过程
for (int i = 1; i <= k + T; i++) {
// 枚举所有可能的跳跃距离
for (int j = S; j <= T; j++)
if (i - j >= 0) // 确保不会跳到负数位置
f[i] = min(f[i], f[i - j] + w[i]); // 状态转移
}
// 在最后可能到达的位置中找最小值
int res = 1e9;
for (int i = k; i < k + T; i++)
res = min(res, f[i]);
printf("%d\n", res);
return 0;
}