nyoj 586 疯牛(二分+贪心)
2015-08-22 10:04
465 查看
疯牛
时间限制:1000 ms | 内存限制:65535 KB难度:4
描述农夫 John 建造了一座很长的畜栏,它包括N (2 <= N <= 100,000)个隔间,这些小隔间依次编号为x1,...,xN (0 <= xi <= 1,000,000,000).
但是,John的C (2 <= C <= N)头牛们并不喜欢这种布局,而且几头牛放在一个隔间里,他们就要发生争斗。为了不让牛互相伤害。John决定自己给牛分配隔间,使任意两头牛之间的最小距离尽可能的大,那么,这个最大的最小距离是什么呢?
输入有多组测试数据,以EOF结束。
第一行:空格分隔的两个整数N和C
第二行——第N+1行:分别指出了xi的位置
输出每组测试数据输出一个整数,满足题意的最大的最小值,注意换行。
样例输入
5 3 1 2 8 4 9
样例输出
3
题意要表达的是:把C头牛放到N个带有编号的隔间里,使得任意两头牛所在的隔间编号的最小差值最大。例如样例排完序后变成1 2 4 8 9,那么1位置放一头牛,4位置放一头牛,它们的差值为3;最后一头牛放在8或9位置都可以,和4位置的差值分别为4、5,和1位置的差值分别为7和8,不比3小,所以最大的最小值为3。
分析:这是一个最小值最大化的问题。先对隔间编号从小到大排序,则最大距离不会超过两端的两头牛之间的差值,最小值为0。所以我们可以通过二分枚举最小值来求。假设当前的最小值为x,如果判断出最小差值为x时可以放下C头牛,就先让x变大再判断;如果放不下,说明当前的x太大了,就先让x变小然后再进行判断。直到求出一个最大的x就是最终的答案。
cpp:
#include <stdio.h> #include <stdlib.h> #define Max_size 100020 int x[Max_size]; int N,C; int com(const void *a,const void *b)//排序 { return *(int *)a-*(int *)b; } bool Judge(int v) { //v表示两牛之间最小的距离值 int i; int num=0;//房子编号 int t; for(i=1;i<C;i++)//对牛计数 { t=num+1; while(t<N&&x[t]-x[num]<v)//t跳出时 t==N说明列举了 num之后的所有房子都无法满足两房子之间距离<=v值 t++;//反之,则说明找到了满足条件的房子 if(t==N) return false; num=t; } return true; } int main() { int i; int bottom,top; int mid; while(~scanf("%d%d",&N,&C)) { for(i=0;i<N;i++) scanf("%d",x+i); qsort(x,N,sizeof(x[0]),com);//因为每个房间的坐标是混乱的,所以对每个房间的坐标进行小到大排序 bottom=0;top=(x[N-1]-x[0])*2;//确定上界和下界 while(top-bottom>1) { mid=(top+bottom)/2; if(Judge(mid)) bottom=mid;//mid值能满足条件 说明答案的区间为[mid,top) else top=mid;//mid 值不能满足条件 说明答案的区间为(bottom,mid) } printf("%d\n",bottom); } return 0; }
#include<stdio.h> #include <stdlib.h> int cmp(const void*a,const void *b) { return *(int *)a-*(int *)b; } int a[1000001]; int main() { int i,c,h,sum; while(scanf("%d%d",&h,&c)!=EOF) { for(i=0;i<h;i++) scanf("%d",&a[i]); qsort(a,h,sizeof(a[0]),cmp); int max=a[h-1]-a[0];//二分搜索的范围,这里Max是两头牛相距的最大范围 int min=0,mid; while(max>=min) { mid=(min+max)/2;//截取中间的这个点 int m=1,n=0; sum=0; while(m<h) { if(a[m]-a >=mid)//领M个元素与第N个元素比较,如果大于这个等于Mid,说明这个距离可以放牛, { // 然后把N的值改变,n=m,让下一个m++元素与这个n比较, sum++; //同时记录符合这个距离的情况有几种,sum++; n=m; } m++; } if(sum>=c-1)//如果这种情况是大于c-1头牛的,说明答案在 【mid+1,max】中 { min=mid+1; } else //如果这种情况是小于c-1头牛的,说明答案在 【min,mid-1】中 { max=mid-1; } } printf("%d\n",min-1); } return 0; }
这个是贪心和二分.二分查找又是折半查找,首先,元素是升序排列,每次查找中间元素和待查找元素进行比较,如果相同,就返回中间元素的位置值,如果不相同且中间元素大于待查找元素就从右边开始,如果不相同且中间元素小于待查找元素就从左边开始,适用于不经常变动而且查找频繁的有序列表。
相关文章推荐
- MySQL字符串函数
- 开源软件free download manager在windows defender中报毒
- hdu4313 贪心+并查集
- 阿里巴巴2015实习生笔试真题
- 黑马程序员-foundation框架-NSArray 基本介绍
- Oracle 给字符串补空格、补0
- 第 3 章 Activity 的生命周期
- 2015 Multi-University Training Contest 10 hdu 5407 CRB and Candies
- AngularJs在单击提交后显示验证信息.
- Linux 目录配置标准:FHS:FileSystem Hierarchy Standard
- Start Page of C
- luncene RAMDirectory
- Java局部内部类和final变量
- Struts(5)简单实例HelloWorld
- spfa邻接表版本
- hdu4318 最短路变形
- Jordan标准形
- Java网络编程叶存菜鸟笔记InetAddress
- uva 11732 "strcmp()" Anyone? (trie+左儿子右兄弟表示法)
- READ TABLE 读取数据(转载自ignativshoo)