二分答案——洛谷P2678跳石头
- 问题描述
- 算法分析:
这道题目准确的说,用爆搜或者枚举,必然吃T,看起来这道题目和之前看到的二分答案没什么相似点,其实我们观察题目可以发现
求最短距离的最大值很快可以联想到用二分答案这种变形二分思想考虑问题,我们依旧是寻找两块石头之间的距离,在l = 0, r = 整个石子区间的长度 之间的区间进行查找,然后写一个check函数, 在check函数中我们中我们枚举两个石子之间的距离与所查找到的距离x作比较,小于该距离x的,说明可以搬动该石子,将计数器cnt++,然后在记录一下下标,更新即可,最后与搬动次数m比较,如果cnt <= m 我们会发现我们可以在右区间进行扫描,l = mid + 1 -> r, 反之,在左区间l -> r = mid - 1扫描.
check函数实现:
//now代表更新下标, cnt计数器
bool check(int x) {
int cnt = 0, now = 0;
for (int i = 1; i <= n; i++) {
if (a[i] - a[now] < x) cnt++;
else now = i;
}
return cnt <= m;
}
- AC代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e4 + 5;
int a[maxn];
int L, m, n;
bool check(int x) {
int cnt = 0, now = 0;
for (int i = 1; i <= n; i++) {
if (a[i] - a[now] < x) cnt++;
else now = i;
}
return cnt <= m;
}
int main() {
scanf("%d%d%d", &L, &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
int ans = 0;
int l = 0, r = L;
while (l <= r) {
int mid = (l + r) >> 1;
if (check(mid)) {
ans = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
printf("%d\n", ans);
return 0;
}
欢迎关注 ly’s Blog