题意:
1243 排船的问题
一个码头中有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艘船到第二根木桩的距离。
输入
第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),并且给出的数据是有序的。
输出
输出最长绳子的最小值。如果码头排不下所有船则输出-1。
输入样例
3 2 16
1
3
14
输出样例
3
思路:
二分答案
直接好家伙,居然是二分答案,
还是太菜了,连最小化最大值用二分答案写都忘了,更离谱的是读错了题,wuwuwuwuwu。。。菜,永恒的菜。。。。。。
(1)这道题如果2 * n * x > m 直接输出 -1,肯定是木有问题的,对吧!!
(2)二分没什么问题,关键在于判断,怎么判断呢?????
贪心写
就像这道题,所有的船都是尽量往最左边放的。。。刚开始看到尽量往最左边放的时候我一脸懵。。
首先我们一定要先明确要求的是“船中间到木桩的距离,就是所需的绳子的长度。由你安排船的位置,使得所用到的最长的绳子最短。输出这个最短的长度”。。n个木桩,n条船,什么意思,说明一对一呗,所以对于每条船,我们现在假设第一条船吧。
1. 船的中间在木桩左边或在木桩位置的情况:
当前head = 0,x = 2,p[1] = 5 , mid = 2可以得到head + x + mid < p[1],这个时候是可以放船的。。但是船的中间只能和p[1]相距2,所以head = max(head, p[1] - mid - x)更新为1。tail加上2 * x就可以了
2.在木桩右边的情况:
首先,可想而知,如果head + x - p[i] > mid 现在所需要的绳子的长度要大于mid,mid就不是当前最大的了,return 0就可以。。。。不然就直接head不变,tail加2 * x就好了
注意在匹配每一条船和每一个木桩的时候head == tail。。。
3.最后比较tail和m的大小就好了
代码实现:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<stack>
#include<queue>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<cstdlib>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 5;
ll n,x,m;
ll p[maxn];
ll ans = 1e14;
bool check(ll xx){
ll start = 0;
ll tail = 0;
for(int i = 1;i <= n;i++){
start = tail;
if(start + x + xx <= p[i]){
start = max(start,p[i] - xx - x);
tail = start + 2 * x;
}
else{
if(start + x - p[i] > xx){
return 0;
}
tail = start + 2 * x;
}
}
if(tail > m) return 0;
else return 1;
}
int main(){
scanf("%lld%lld%lld",&n,&x,&m);
for(ll i = 1;i <= n;i++){
scanf("%lld",&p[i]);
}
if(n * 2 * x > m){
printf("-1\n");
}
else{
ll l = 0,r = 1e14;
ll mid;
ll ans = 0;
while(l <= r){
mid = (l + r) / 2;
if(check(mid)){
r = mid - 1;
ans = mid;
}
else{
l = mid + 1;
}
}
printf("%lld\n",ans);
}
return 0;
}