1 条题解
-
0
// 包含C++所有标准库头文件,竞赛常用写法 #include<bits/stdc++.h> using namespace std; // 全局变量声明:全局数组默认初始化为0,符合题目起点坐标为0的要求 int L; // 河道总长度(起点到终点的距离) int n; // 河道中间的岩石数量 int M; // 最多可以移除的岩石数量 int a[50005]; // 存储岩石坐标的数组,数组大小适配题目数据范围 n≤5e4 /** * @brief 检查函数:判断当最短跳跃距离为x时,移除的岩石数量是否符合要求 * @param x 假设的最小跳跃距离 * @return bool true=符合要求(可尝试更大距离),false=不符合要求(需缩小距离) */ bool check(int x){ int last = 0; // 记录上一块**保留**的岩石下标,初始为起点(a[0]=0) int cnt = 0; // 统计当前需要移除的岩石总数 // 遍历所有岩石+终点(a[n+1]=L 是终点坐标) for(int i = 1; i <= n+1; i++){ // 如果当前岩石到上一块保留岩石的距离 小于 预设最小距离x // 说明这块岩石必须移除,否则无法满足最小跳跃距离要求 if(a[i] - a[last] < x) { cnt++; } else { // 距离满足要求,保留当前岩石,更新上一块保留岩石的下标 last = i; } } // 若移除总数≤最大允许移除数M,说明当前x是可行的 return cnt <= M; } /** * @brief 二分查找函数:寻找满足条件的最大最短跳跃距离(题目所求答案) * @return int 最终的最优解 */ int find (){ // 二分查找的左右边界初始化 int l = 0; // 左边界:最小可能的跳跃距离为0 int r = 1e8 + 1; // 右边界:最大可能的跳跃距离(大于题目河道长度上限,覆盖所有情况) // 二分核心循环:左边界+1 < 右边界时持续查找,避免死循环 while(l + 1 < r){ // 计算中间值,等价于 (l+r)/2,右移运算效率更高 int mid = (l + r) >> 1; // 判断mid这个距离是否可行 if(check(mid)){ // 可行:尝试寻找更大的距离,更新左边界为mid l = mid; } else { // 不可行:距离太大,需要缩小范围,更新右边界为mid r = mid; } } // 循环结束时,l即为满足条件的最大最短跳跃距离 return l; } // 主函数:程序入口 int main(){ // 输入三个核心参数:河道总长L、岩石数n、最多移除数M cin >> L >> n >> M; // 循环读取n块岩石的坐标,存入数组a[1]~a[n] for(int i = 1; i <= n; i++){ cin >> a[i]; } // 给数组最后一位赋值为L,代表终点坐标,方便统一遍历计算 a[n+1] = L; // 调用二分函数计算答案,并输出结果 cout << find(); return 0; }
- 1
信息
- ID
- 1390
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 10
- 标签
- 递交数
- 4
- 已通过
- 1
- 上传者
粤公网安备44195502000169号