题目大意:一群牛要过河,河中有许多石墩,FJ为了锻炼牛的跳跃力,将其中的m个石墩摘掉,求所有情况中最大的跳跃最小值。
思路:用一个变量sum累加,跳跃值mid通过二分来枚举。
(1)如果可以摘除的石墩超过m的话,说明牛的跳跃值太大了,并不是最小跳跃值。
(2)如果可以摘除的石墩刚好等于m的话,也不一定是最小的。
(3)如果小于m的话,说明mid偏小。
CODE:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int SIZE = 50010;
int high_bound, low_bound;
int a[SIZE];
int L, m, n;
int BSearch(int x, int y, int m)
{
while(x <= y)
{
int mid = x+(y-x)/2;
int block = 0, sum = 0;
for(int i = 1; i <= n+1; i++)
{
if((sum+=a[i]-a[i-1]) <= mid) block++; //看是否连续的拿走石子,注意是sum+=a[i]-a[i-1]
else sum = 0;
}
if(block <= m) x = mid+1; //当block == m时,但不一定是最小的,<m说明跳跃值偏小。
else y = mid-1;
}
return x;
}
int main()
{
while(~scanf("%d%d%d", &L, &n, &m))
{
low_bound = 0x3f3f3f3f; //跳跃的最小距离
high_bound = L; //跳跃的最大距离
a[0] = 0; a[n+1] = L;
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
sort(a, a+n+2);
for(int i = 1; i <= n+1; i++)
{
low_bound = min(low_bound, a[i]-a[i-1]);
}
int ans = BSearch(low_bound, high_bound, m);
printf("%d\n", ans);
}
return 0;
}
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int SIZE = 50010;
int high_bound, low_bound;
int a[SIZE];
int L, m, n;
int BSearch(int x, int y, int m)
{
while(x <= y)
{
int mid = x+(y-x)/2;
int block = 0, sum = 0;
for(int i = 1; i <= n+1; i++)
{
if((sum+=a[i]-a[i-1]) <= mid) block++; //看是否连续的拿走石子,注意是sum+=a[i]-a[i-1]
else sum = 0;
}
if(block <= m) x = mid+1; //当block == m时,但不一定是最小的,<m说明跳跃值偏小。
else y = mid-1;
}
return x;
}
int main()
{
while(~scanf("%d%d%d", &L, &n, &m))
{
low_bound = 0x3f3f3f3f; //跳跃的最小距离
high_bound = L; //跳跃的最大距离
a[0] = 0; a[n+1] = L;
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
sort(a, a+n+2);
for(int i = 1; i <= n+1; i++)
{
low_bound = min(low_bound, a[i]-a[i-1]);
}
int ans = BSearch(low_bound, high_bound, m);
printf("%d\n", ans);
}
return 0;
}