題目大意是,河中有排列一些石頭,石頭所在的位置都不同,可以拿去其中的幾塊石頭,但是開始和結束位置的石頭不能去掉,使得這些石頭之間的最小距離最大。
這題就是最大化最小值,我們可以用二分搜索來解決這個問題。直接套用二分法的模型,定義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;
}