1243 排船的问题
题目来源: Codility
基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 收藏 关注
一个码头中有N艘船和N个木桩,船的长度为2*X,码头的宽度为M,N个木桩的位置(相对码头左岸的位置)会在数据中给出。船和船之间不能重叠,即每艘船的船头不能超过上一艘船的船尾,当然也不能超出码头的两岸。船和木桩之间用绳子连接,并且1个木桩只能栓1条船,绳子的一头拴在木桩上,另一头拴在船的中间。而船中间到木桩的距离,就是所需的绳子的长度。由你根据给出的条件,排列船的位置,使得所用到的最长的绳子最短。输出这个最短的长度,如果码头排不下所有船则输出-1。
例如:N = 3, X = 2, M = 16。三个木桩的位置为:1 3 14。船的长度为2*X = 4。你可以将三艘船放在2 6 14(指的是船中间所处的位置),这样船和船之间既没有重叠,并且所用的最长的绳子最短,长度为3,即第2艘船到第二根木桩的距离。
Input
第1行:3个数N X M,中间用空格分隔(1 <= N <= 50000, 1 <= X <= 10^9, 1 <= M <= 10^9)。
第2 - N + 1行:每行1个数Pi,对应木桩的位置(0 <= Pi <= Pi+1 <= M),并且给出的数据是有序的。
Output
输出最长绳子的最小值。如果码头排不下所有船则输出-1。
Input示例
3 2 16
1
3
14
Output示例
3
李陶冶 (题目提供者)
二分绳子的最大长度dis
显然对每条小船 在距离木桩<=dis的情况下 越往左越有利
小船i的中心坐标pos=max(p[i]-dis,l+x); | l=左边界
#include <bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define MEM(a,x) memset(a,x,sizeof(a))
using namespace std;
const int inf=1e9+7;
const int N = 50000+5;
int p[N];
int n,x,m;
bool check(int dis){
int l=0;
for(int i=0;i<n;++i){
int pos=max(p[i]-dis,l+x);
if(abs(pos-p[i])<=dis&&pos+x<=m){
l=pos+x;
}
else{
return false;
}
}
return l<=m;
}
int binarySearch(){
int l=0,r=m+1;
int ans=m+1;
while(l<=r){
int mid=(l+r)/2;
if(check(mid)){
ans=mid;
r=mid-1;
}
else{
l=mid+1;
}
}
return ans;
}
int main()
{
//freopen("/home/lu/code/r.txt","r",stdin);
while(~scanf("%d%d%d",&n,&x,&m)){
for(int i=0;i<n;++i){
scanf("%d",&p[i]);
}
int ans=binarySearch();
printf("%d\n",ans==m+1?-1:ans);
}
return 0;
}