题目大意是,河中有排列一些石头,石头所在的位置都不同,可以拿去其中的几块石头,但是开始和结束位置的石头不能去掉,使得这些石头之间的最小距离最大。
这题就是最大化最小值,我们可以用二分搜索来解决这个问题。直接套用二分法的模型,定义C(X):=石头之间的距离都不小于X。然后进行二分搜索满足条件的最大X值。
确定石头距离是否能满足距离不小于X,只要对石头排序后,依次判断当前石头是否和之前的石头距离小于X如果小于,则去掉当前石头,这一步的复杂度O(n),总共的复杂度
便是O(nLog(P)),P为开始位置和结束位置石头的距离。
#include <stdio.h>
#include <vector>
#include <math.h>
#include <string.h>
#include <string>
#include <iostream>
#include <queue>
#include <list>
#include <algorithm>
#include <stack>
#include <map>
using namespace std;
int StonePos[50003];
int Dis[50003];
bool CC(int x, int N, int M)
{
int curcount = 0;
int curLeft = -1;
for (int i = 0; i < N;i++)
{
if (Dis[i] < x)
{
if (i == N - 1 && curcount < M)
{
if (curLeft >= 0)
{
if (Dis[i] + curLeft < x)
{
return false;
}
}
else
return false;
}
else if (curcount < M)
{
Dis[i + 1] += Dis[i];
curcount++;
}
else
return false;
}
else
{
curLeft = i;
}
}
return true;
}
int compp(const void* a1, const void* a2)
{
return *(int*)a1 - *(int*)a2;
}
int main()
{
#ifdef _DEBUG
freopen("e:\\in.txt", "r", stdin);
#endif
int L, N, M;
scanf("%d %d %d\n", &L, &N, &M);
StonePos[0] = 0;
for (int i = 1; i <= N;i++)
{
scanf("%d\n", &StonePos[i]);
}
StonePos[N + 1] = L;
qsort(StonePos, N + 2, sizeof(int), compp);
for (int i = 0; i <= N;i++)
{
StonePos[i] = StonePos[i + 1] - StonePos[i];
}
int l = 0;
int r = L * 2;
while (r - l > 1)
{
memcpy(Dis, StonePos, sizeof(Dis));
int mid = (l + r) / 2;
if (CC(mid, N + 1, M))
{
l = mid;
}
else
r = mid;
}
printf("%d\n", l);
return 0;
}