51nod 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艘船到第二根木桩的距离。

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

解题思路:

一看到最长的绳子最短,就想到了二分,确实,这题二分是可以解决的,可是还有更好的的O(n)的方法,想想也挺有趣的。

首先把所有的小船都从左到右并排排列,再把他们向右移动,但是移多少是个问题,移多了,少了都不是最小值,在小船

向右移动的过程主要看右边木桩到船心的最小值,可以用最小值来中和,取他俩的平均值,这样最小的不至于太小,最大的也

不会太大。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=50000+100;
int a[maxn];
int b[maxn];//记录第i个及i个之后的木桩到船心的最小距离
int bbs(int x)
{
    if(x<0)
        return -x;
    return x;
}
int main()
{
    int n,x;
    int m;
    scanf("%d%d%d",&n,&x,&m);
    for(int i=0; i<n; i++)
    {
        scanf("%d",&a[i]);
    }
    if(m/2/x<n)
    {
        printf("-1\n");
    }
    else
    {
        int ans=0,cur=0;
        for(int i=n-1;i>=0;i--)
        {
            b[i]=a[i]-(i*2*x+x);
            if(i<n-1)
            b[i]=min(b[i],b[i+1]);
        }
        for(int i=0;i<n;i++)
        {
            int temp=(a[i]-(i*2*x+x)-cur+b[i]-cur)/2;
            if(temp>0)
            {
                cur+=min(temp,m-n*x*2-cur);
            }
            ans=max(ans,bbs(a[i]-(i*2*x+x)-cur));
        }
        cout<<ans<<endl;
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-05 21:33:27

51nod 1243 排船的问题(锻炼思维的好题)的相关文章

51nod 1243 排船的问题(二分)

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1243 题意: 思路: 二分来做,每次贪心的把船安排到能安排的最左边即可. 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<stack>

51nod 1391 01串(锻炼思维的好题)

题目http://www.51nod.com/onlineJudge/questionCode.html#problemId=1391?iceId=20917 1391 01串 题目来源: Codility 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 给定一个01串S,求出它的一个尽可能长的子串S[i..j],满足存在一个位置i<=x <=j, S[i..x]中0比1多,而S[x + 1..j]中1比0多.求满足条件的最长子串长度. Input 一行包含

51nod 1287 加农炮(锻炼思维的好题)

题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1287 一个长度为M的正整数数组A,表示从左向右的地形高度.测试一种加农炮,炮弹平行于地面从左向右飞行,高度为H,如果某处地形的高度大于等于炮弹飞行的高度H(A[i] >= H),炮弹会被挡住并落在i - 1处,则A[i - 1] + 1.如果H <= A[0],则这个炮弹无效,如果H > 所有的A[i],这个炮弹也无效.现在给定N个整数的数组B代表炮弹高度

51nod 1243 二分+贪心

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1243 1243 排船的问题 题目来源: Codility 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 收藏 关注 一个码头中有N艘船和N个木桩,船的长度为2*X,码头的宽度为M,N个木桩的位置(相对码头左岸的位置)会在数据中给出.船和船之间不能重叠,即每艘船的船头不能超过上一艘船的船尾,当然也不能超出码头的两岸.船和木桩之间用绳子

10种锻炼思维的方法,让你大脑更强大!

有人说:穷人穷脑袋,富人富思维: 如何让你的大脑更强大,更具有威力? 其实开拓思维顾名思义就是开发大脑,只要跟开发大脑有关的方法,同样可以用来开拓你的思维. 1.联想法 拿两个A 物体和B物体,一定是不同的哦,关系距离越远越好.然后让孩子想办法用一句话,或者一段话把他们联系在一起. 就像造句,看图写作一样,熟练之后,就用3个物体,4个物体,甚至更多. 当然不一定要规规矩矩去造句,造段.越离谱,效果会越好的.联想就是要突破局限,所以不要限制孩子的想象. 2.观察法 让孩子专注观察一个物体或一个人物

51Nod 1003 阶乘后面0的数量 | 思维

题意:n的阶乘后面0的个数,如果直接算出阶乘再数0的数量一定会超时的. 因为10=2*5,所以求出5贡献的次数就行. #include "bits/stdc++.h" using namespace std; #define LL long long #define INF 0x3f3f3f3f3f #define PI acos(-1) #define N 510 LL arr[N]; int main() { int n,k; while(~scanf("%d"

每天一个JS 小demo之原生数组splice方法书写。主要知识点:锻炼思维逻辑能力,对于数组方法的理解和各种情况的考量

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head> <body><script>/** splice(start, deleteCount, data1, data2, data3...)* */ var arr = ['a', 'b'

poj 1837 Balance 动态规划 (经典好题,很锻炼思维)

题目大意:给你一个天平,并给出m个刻度,n个砝码,刻度的绝对值代表距离平衡点的位置,并给出每个砝码的重量.达到平衡状态的方法有几种. 题目思路:首先我们先要明确dp数组的作用,dp[i][j]中,i为放置的砝码数量,j为平衡状态,0为平衡,j<0左倾,j>0右倾,由于j作为下标不能是负数,所以我们要找一个新的平衡点,因为15*20*20 = 7500,所以平衡点设置为7500, 然后我们可以得出动态方程 dp[i][j+w[i]*c[k])+=dp[i-1][j]; #include<c

51Nod 1110 距离之和最小 V3 中位数 思维

基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 X轴上有N个点,每个点除了包括一个位置数据X[i],还包括一个权值W[i].点P到点P[i]的带权距离 = 实际距离 * P[i]的权值.求X轴上一点使它到这N个点的带权距离之和最小,输出这个最小的带权距离之和.Input第1行:点的数量N.(2 <= N <= 10000)第2 - N + 1行:每行2个数,中间用空格分隔,分别是点的位置及权值.(-10^5 <= X[i] <= 10^5,1 &