【51NOD-1243-排船问题】 二分

51NOD1243排船问题
题意
N N 2 X M 一个码头中有N艘船和N个木桩,船的长度为2*X,码头的宽度为M
N N个木桩的位置(相对码头左岸的位置)会在数据中给出
船和船之间不能重叠,即每艘船的船头不能超过上一艘船的船尾,当然也不能超出码头的两岸
1 1 船和木桩之间用绳子连接,并且1个木桩只能栓1条船,绳子的一头拴在木桩上,另一头拴在船的中间
而船中间到木桩的距离,就是所需的绳子的长度。由你根据给出的条件,排列船的位置
使 1 使得所用到的最长的绳子最短。输出这个最短的长度,如果码头排不下所有船则输出-1。
做法
我们发现答案肯定是具有二分性质的,所以我们只要二分答案验证即可
验证答案是否可行的时候,尽量把船靠的最近,看最后一个船是否超过右边界即可
代码

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define dbg(x) cout<<#x<<" = "<<x<<endl
const int maxn = 5e4+10;
int a[maxn];
int n,x,m;
bool check(int mid)
{
    int head=0,tail=0;
    for(int i=1;i<=n;i++)
    {
        head=tail;
        if(head+x-mid<=a[i])
        {
            if(head+x+mid<=a[i])
            {
                head=a[i]-x-mid;
                tail=head+2*x;
            }
            else
            {
                tail+=2*x;
            }
        }
        else
        {
            return 0;
        }
    }
    return tail<=m;
}
int main()
{
    scanf("%d%d%d",&n,&x,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    int l=0,r=m-1;
    while(l<=r)
    {
        int mid=(l+r)/2;
        if(check(mid)) r=mid-1;
        else l=mid+1;
    }
    if(l==m||2*n*x>m) printf("-1\n");
    else printf("%d\n",l);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38891827/article/details/83281213
今日推荐