洛谷:P2678
OJ: I4953
问题分析:
解决方案:
isPossible
:
cnt
加一。cnt
超过了 M
,则在当前的 D 下不可行,返回 false
。cnt
不超过 M
,说明在当前的 D 下可行,返回 true
。代码实现:
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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | /**************************************************************** * Description: 2015_S_semi_4 跳石头 * Author: Alex Li * Date: 2024-09-19 19:46:20 * LastEditTime: 2024-09-19 20:25:01 ****************************************************************/ #include <iostream> #include <vector> #include <algorithm> using namespace std; // 检查在最小跳跃距离为 D 的情况下,是否可以通过移除不超过 M 个岩石,从起点跳到终点 bool isPossible(const vector<int>& positions, int N, int M, int D) { int cnt = 0; // 已移除的岩石数量 int prev = 0; // 上一个未被移除的岩石在 positions 中的索引,初始为起点 int size = positions.size(); // 岩石总数(包括起点和终点) // 遍历所有岩石,从起点开始 for (int i = 1; i < size; ++i) { // 计算当前岩石与上一个未被移除的岩石之间的距离 int distance = positions[i] - positions[prev]; if (distance < D) { // 如果距离小于最小跳跃距离 D,需要移除当前岩石 cnt++; if (cnt > M) { // 如果移除的岩石数量超过允许的最大值 M,则无法实现,返回 false return false; } // 当前岩石被移除,prev 不变,继续检查下一块岩石 } else { // 如果距离大于等于 D,更新 prev 为当前岩石的索引 prev = i; } } // 遍历完成且移除的岩石数量不超过 M,返回 true return true; } int main() { int L, N, M; cin >> L >> N >> M; // 读取起点到终点的距离 L,岩石数量 N,最多可移除的岩石数 M vector<int> positions(N + 2); // 创建一个大小为 N+2 的向量,包含起点和终点 positions[0] = 0; // 起点位置为 0 for (int i = 1; i <= N; ++i) { cin >> positions[i]; // 读取第 i 块岩石的位置 } positions[N + 1] = L; // 终点位置为 L sort(positions.begin(), positions.end()); // 对所有岩石位置进行排序 int low = 0; // 二分查找的下界,最小可能的最小跳跃距离 int high = L; // 二分查找的上界,最大可能的最小跳跃距离 // 开始二分查找,寻找最大化的最小跳跃距离 while (low < high) { // 取中间值,向上取整,避免无限循环 int mid = (low + high + 1) / 2; // 检查在最小跳跃距离为 mid 的情况下,是否可行 if (isPossible(positions, N, M, mid)) { // 如果可行,说明可以尝试更大的最小跳跃距离,更新 low low = mid; } else { // 如果不可行,说明最小跳跃距离过大,更新 high high = mid - 1; } } // 输出最大化的最小跳跃距离 cout << low << endl; return 0; } |