另外一个贪心算法的例子,题目是这样的
疯牛
时间限制:
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决定自己给牛分配隔间,使任意两头牛之间的最小距离尽可能的大,那么,这个最大的最小距离是什么呢?-
输入
-
-
下面是我查了网上的文章后自己总结的解题思路:
- 先把所有的隔间位置按从小到大排序,于是有1 2 4 8 9,于是题目转化成在1~9之间找到一个数,使它与1和9的距离的最小值最大,也就是越靠近中间越符合要求
- 运用二分枚举法找出这个距离的最小值。最小值有好几个,有1 ( 1 ->2->x, x->8->9) 2 ( 2 ->4->8, 2->4->9 ) 3 (1->4->8, 1->4->9)
- 但还要找到最小值里的最大值,于是要用到贪心算法找到最大值。
二分枚举的框架是这样的
while(low<high)
{
int mid = (low+high)/2;
if(<)low = mid+1; // mid取的太小了
else high = mid;
}
下面是这题的代码。
以6 3 + 1 2 4 8 9这组输入 来解释下面的代码
首先把题目转换成在一条距离为8的线段内找到一K(K=1)个点,使得这个点到另外几个点的最短距离最大
- 用二分枚举法,初始状态 low=0,high=8, mid=4
- 调用check()函数,目的是遍历所有的数据,找到至少C(C=3)个点使得这几个点的距离至少为mid(mid=4)
- 显然找不到这样一个点,使它到1和9的距离都>=4. 说明mid选大了,于是high-1,使mid变小点;
- 同理,如果找到了至少C个点,那说明mid选小了,于是low+1,使mid变大点;
#include"iostream"
#include "stdlib.h"
#include "stdio.h"
#include "algorithm"
using namespace std;
int N,C; //N 表示隔间的数目,C 表示牛的数目
bool check(int *(&a),int mid)
{
int temp=a[0];
int cow=1; // 表示符合要求的牛的数目
for(int i=1;i<N;i++)
{
if(a[i]-temp>=mid) //每找到一个符合要求的牛
{
cow++;
temp=a[i];
}
if(cow>=C)
return true;
}
return false;
}
int binary_enum(int *(&a))
{
int low = 0;
int high=a[N-1]-a[0];
int mid;
while(low<=high)
{
mid=(low+high)/2;
if(check(a,mid)) low=mid+1;
else high=mid-1;
}
return low-1;
}
int main()
{
while(EOF!=scanf("%d%d",&N,&C))
{
int *a=new int[N];
int i;
for(i=0;i<N;i++)
cin>>a[i];
sort(a,a+N);
cout<<binary_enum(a)<<endl;
delete a;
}
return 0;
}