51nod 1243 排船的问题(锻炼思维的好题)
2015-08-31 18:58
465 查看
一个码头中有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
Output
Input示例
Output示例
解题思路:
一看到最长的绳子最短,就想到了二分,确实,这题二分是可以解决的,可是还有更好的的O(n)的方法,想想也挺有趣的。
首先把所有的小船都从左到右并排排列,再把他们向右移动,但是移多少是个问题,移多了,少了都不是最小值,在小船
向右移动的过程主要看右边木桩到船心的最小值,可以用最小值来中和,取他俩的平均值,这样最小的不至于太小,最大的也
不会太大。
代码:
例如: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; }
相关文章推荐
- RaspiCam: C++ API for using Raspberry camera with/without OpenCv
- 单例集合知识点总结
- Win10开发:文件操作之FileOpenPicker、FileSavePicker和FolderPicker
- 智能聊天机器人小黄鸡及其制作方法
- HDU3488Tour(KM最小费用圈覆盖)
- Xcode中自定义代码块,只要在Xcode中操作即可
- 数据流重定向
- 内存映射操作
- 判断某个app是否安装
- AWS申请图文及连接教程
- 九度OJ,题目1089:数字反转
- sed 简明教程
- Memo Mirantis Fuel 6.0安装札记
- (4.2.16.2)Android判断当前应用程序处于前台还是后台的两种方法
- hdu 2846 Repository - 字典树
- 如何卸载Eclipse中ArcGIS for Android的旧版本?
- 泛型编程
- php电商系统iwebshop二次开发教程第一讲《iwebshop框架结构》
- IOS开发Block代码块基本语法使用-从基础到高级
- Java 字符串比较