http://www.51nod.com/onlineJudge/questionCode.html#!problemId=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
虽然分类是dp,但一眼看去就是二分呀,,于是愉快的错了一晚上,最后删了重写几遍才过。
对于一个最长长度x,判断他是否能满足要求,用pos记录上一个船的尾部位置,如果x[i]<=pos+X,显然接着上一个船放置最优,如果不合法显然往后放置更不会合法。
否则的话,将船尽可能的往左边放置,能正好在xi左边-k处就这样放,如果不足k的话接着上一个放置即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define LL long long 4 LL mod=1e9+7; 5 int x[50005],N,X,M; 6 bool ok(int k) 7 { 8 int pos=0,len=X*2; 9 for(int i=1;i<=N;++i) 10 { 11 if(x[i]<=pos+X){ 12 if(pos+X-x[i]<=k) pos+=len; 13 else return 0; 14 } 15 else{ 16 if(x[i]-(pos+X)<=k) pos+=len; 17 else pos=x[i]-k+X; 18 } 19 } 20 return pos<=M; 21 } 22 int main() 23 { 24 int i,j,k; 25 scanf("%d%d%d",&N,&X,&M); 26 for(i=1;i<=N;++i) 27 { 28 scanf("%d",x+i); 29 } 30 int l=0,r=M; 31 while(l<r) 32 { 33 int mid=l+(r-l)/2; 34 if(ok(mid)) r=mid; 35 else l=mid+1; 36 } 37 38 if(ok(l)) cout<<l<<endl; 39 else puts("-1"); 40 return 0; 41 }
时间: 2024-10-09 22:08:20