链接:点击打开链接
题意:一个码头中有N艘船和N个木桩,船的长度为2*X,码头的宽度为M,N个木桩的位置(相对码头左岸的位置)会在数据中给出。船和船之间不能重叠,即每艘船的船头不能超过上一艘船的船尾,当然也不能超出码头的两岸。船和木桩之间用绳子连接,并且1个木桩只能栓1条船,绳子的一头拴在木桩上,另一头拴在船的中间。而船中间到木桩的距离,就是所需的绳子的长度。由你根据给出的条件,排列船的位置,使得所用到的最长的绳子最短。输出这个最短的长度,如果码头排不下所有船则输出-1。
代码:
#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
int N,X,M;
int p[50005];
int judge(int d){
int i,j,st,en,sum;
st=2*X,sum=0; //st的意义是当前这条船的船尾最靠左能放的位置
for(i=0;i<N;i++){
if(abs(st-p[i]-X)<=d){ //符合每条绳子的长度都小于等于d时,第i条船一定
st+=2*X; //在以第i条木桩为中点的一条线段内,因此当st已经
continue; //在区间内时直接推出下一个st,如果小于左边界,则
} //将st赋成左边界,否则return 0,因为在边界内的话
else{ //是不会进行到这一步的,所以直接return 0
if(p[i]-d+X>st)
st=p[i]-d+X;
else
return 0;
st+=2*X;
}
}
if(st-2*X>M)
return 0;
return 1;
}
int main(){
int i,j,l,r,mid,ans;
while(scanf("%d%d%d",&N,&X,&M)!=EOF){
for(i=0;i<N;i++)
scanf("%d",&p[i]);
if(N*2*X>M){
puts("-1");
continue;
}
l=0;r=M; //二分绳子长度
while(r>=l){
mid=(l+r)/2;
if(judge(mid)){
ans=mid;
r=mid-1;
}
else
l=mid+1;
}
printf("%d\n",ans);
}
return 0;
}