传送门
问题:
第一行给出L,n,m。分别代表河水的宽,河水中有n个石头,和青蛙最多能跳m次。。
青蛙只能跳到石头上,且默认可以跳无限远。
下面给出n个石头的坐标。
问:要求使得青蛙跳过河的这次所有的跳跃中,跳跃最远的那次距离尽可能最小,输出这个值
分析:
1、如果m > n,那一定是两两相距最远的那个距离。
2、数据很大,暴力去查找每一个跳跃的方案肯定会超时。
3、用二分去查找一个单次跳跃的最大距离,看以这个距离能否完成。直到找到最小的那个数
二分的上边界是河水宽 L 。
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 1e5*5+10;
int L,n,m;
int a[MAXN];
bool judge(int dis)
{
// 如果这个距离跳m次还不够
if(dis*m < L) return false;
int step,i;
step = 0;
i = 0;
while(i <= n)
{
if(dis < a[i]) return false; //存在两个石头间的距离比dis大,
int t = dis;
while(t >= a[i])
t -= a[i++];
step++;
}
if(step > m) return false;
return true;
}
int BS(int l, int r)
{
while(l <= r)
{
int M = (l+r)/2;
if(judge(M)) // 如果当前距离M足够,减少试试看
r = M - 1;
else // 如果当前距离不够,需要增加
l = M + 1;
}
return l;
}
int main()
{
ios::sync_with_stdio(false);
while(cin >> L >> n >> m)
{
a[0] = 0;
for(int i = 1; i <= n; i++)
cin >> a[i];
a[n+1] = L;
sort(a,a+n+2);
int maxd = 0;
for(int i = 0; i <= n; i++)
{
a[i] = a[i+1] - a[i];
maxd = max(maxd,a[i]);
}
if(m > n)
cout << maxd << endl;
//对每次需要跳的最大距离进行二分
//显然,如果每个石头都跳,那么最大距离就是两个相邻的最远石头的距离
// 如果一次跳过,那就是L
else
{
int ans = BS(maxd, L);
cout << ans << endl;
}
}
return 0;
}