Aggressive cows(愤怒的牛)(分治)
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 40455 Accepted: 18254
Description
Farmer John has built a new long barn, with N (2 <= N <= 100,000) stalls. The stalls are located along a straight line at positions x1,…,xN (0 <= xi <= 1,000,000,000).
His C (2 <= C <= N) cows don’t like this barn layout and become aggressive towards each other once put into a stall. To prevent the cows from hurting each other, FJ want to assign the cows to the stalls, such that the minimum distance between any two of them is as large as possible. What is the largest minimum distance?
Input
- Line 1: Two space-separated integers: N and C
- Lines 2…N+1: Line i+1 contains an integer stall location, xi
Output
- Line 1: One integer: the largest minimum distance
Sample Input
5 3
1
2
8
4
9
Sample Output
3
题目大意:
农场主约翰新建了一个有n个牛棚的农舍,这些牛棚位于一条直线x1,x2,x3…xn(0<=xi<=1,000,000,000)上。他的c(2<=c<=n)头牛不喜欢这个牛棚的布局,如果把这些牛放在一个牛棚的话,它们就会变得非常愤怒,会攻击其他牛,为了防止这些牛相互攻击,农场主约翰想要把这些牛分散放在牛棚里,就像在两头牛之间尽可能大的最小距离,这个最大化的最小值是多少呢?
输入:
第1行:两个独立的数N(N个牛棚)和C (C头牛)
第2到N+1行:牛舍的位置Xi
输出:最大化的最小距离
分析
把牛舍的位置保存在数组中x[]中,排一下序。
最远的牛栏为x[0]和x[n-1];我们查找一个dis,使得以dis为最小距离时,所有的牛都能放进牛棚。
dis的范围是[1,n-1]。当然我们可以使用枚举法,但效率太低。这里我们可以使用二分搜索,用ans记录能放下所有牛的最大的dis。
首先left=x[0], right=x[n-1], dis=mid=(left+right)/2;
用这个mid去试能不能放下所有牛,如果可以,left=mid+1,更新ans=mid;
如果不可以,right=mid-1;
直到left>=right退出循环。
关键代码
left=x[0];
right=x[n-1];
while(left<=right){
mid=(left+right)/2;
if(check(mid)){
if(mid>ans) ans=mid;
left=mid+1;
}
else{
right=mid-1;
}
}
检查mid是否符合题意
bool Judge(int dis){
int cnt=0;
int i;
int start=x[0];
cnt++;
for(i=1;i<n;i++){
if(x[i]-start>=dis){
cnt++;
start=x[i];
}
}
if(cnt>=c) return true;
else return false;
}
具体实现时可以递归实现,也可以非递归实现。
非递归代码
//非递归
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
//定义 牛舍的数量
int x[100001],n,c;
//判断该距离下牛能否被全部放下
bool Judge(int dis){
//初步定义牛舍中牛的数量以及牛的位置
int cnt=0,i,start=x[0];
//已经在x【0】处放置了一头牛 start记录上一头牛的位置
cnt++;
for(i=1;i<n;i++){
//如果位置适合 放入牛
if(x[i]-start>=dis){
cnt++;
//更新start的值
start=x[i];
//如果牛已经放置完了
if(cnt==c)
break;
}
}
if(cnt>=c)
return true;
else
return false;
}
int main(){
int i=0,left,right,mid;
scanf("%d %d",&n,&c);
for(i=0;i<n;i++)
scanf("%d",&x[i]);
//对牛舍进行排序
sort(x,x+n);
//二分法查找最合适的距离
left=x[0];
right=x[n-1];
while(left<=right){
mid=(left+right)/2;
//调用check函数 如果足够装得下这c头奶牛 说明mid小于所求解 需要更新mid
if(Judge(mid)){
left=mid+1;
}
else{
right=mid-1;
}
}
printf("%d",right);
return 0;
}
递归代码
//递归
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
//定义 牛舍的数量
int x[100001],n,c;
//判断该距离下牛能否被全部放下
bool Judge(int dis){
//初步定义牛舍中牛的数量以及牛的位置
int cnt=0,i,start=x[0];
//已经在x[0]处放置了一头牛 start记录上一头牛的位置
cnt++;
for(i=1;i<n;i++){
//如果位置适合 放入牛
if(x[i]-start>=dis){
cnt++;
//更新start的值
start=x[i];
//如果牛已经放置完了
if(cnt==c)
break;
}
}
if(cnt>=c)
return true;
else
return false;
}
int Search(int left,int right){
int mid;
if(left>right) return right;
mid=(left+right)/2;
if(Judge(mid))
return Search(mid+1,right);
else
return Search(left,mid-1);
}
int main(){
int i=0,left,right,ans;
scanf("%d %d",&n,&c);
for(i=0;i<n;i++)
scanf("%d",&x[i]);
//对牛舍进行排序 ,快排的时间复杂度是O(nlogn)
sort(x,x+n);
//二分法查找最合适的距离
left=x[0];
right=x[n-1];
ans=Search(left,right);
printf("%d",ans);
return 0;
}