描述
题解
万万没想到,这道题用的是二分……
对绳子长度进行二分,然后逐个对比,看能否排放下所有船只,绳子长度在0~M-1
之间,所以……顺理成章的二分,只是查找的不是v
,而是长度为mid
的绳子能否拴住所有的船,这里我们用int judge(int d)
函数来判断,如果能拴住,则说明最长绳子的长度最短小于等于d
,否则大于等于d
,可AC……
代码
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const int MAXN = 5e4 + 5;
int N, X, M;
int P[MAXN];
int judge(int d)
{
int st = 2 * X; // 船尾可以放置的首位置
for (int i = 0; i < N; i++)
{
if (abs(st - P[i] - X) <= d) // 绳子的长度小于等于d
{
st += 2 * X; // 推移到下一个位置
}
else
{
if (P[i] - d + X > st) // 如果在绳长为d时,可以放下船
{
st = P[i] - d + X; // 更新首位置
}
else
{
return 0;
}
st += 2 * X; // 推移到下一个位置
}
}
if (st - 2 * X > M) // 最后一个船越界了
{
return 0;
}
return 1;
}
// 二分
int bs(int left, int right)
{
int ans = M;
int mid;
while (left <= right)
{
mid = (left + right) >> 1;
if (judge(mid))
{
ans = mid;
right = mid - 1;
}
else
{
left = mid + 1;
}
}
return ans;
}
int main(int argc, const char * argv[])
{
cin >> N >> X >> M;
if (2 * X * N > M)
{
cout << "-1\n";
return 0;
}
for (int i = 0; i < N; i++)
{
scanf("%d", P + i);
}
// 二分,绳子长度为0到M-1
int ans = bs(0, M - 1);
std::cout << ans << '\n';
return 0;
}