POJ 2456 Aggressive cows ( 二分 && 贪心 )
题意 : 农夫 John 建造了一座很长的畜栏,它包括N (2 <= N <= 100,000)个隔间,这些小隔间依次编号为x1,...,xN (0 <= xi <= 1e9)。但是,John的C (2 <= C <= N)头牛们并不喜欢这种布局,而且几头牛放在一个隔间里,他们就要发生争斗。为了不让牛互相伤害。John决定自己给牛分配隔间,使任意两头牛之间的最小距离尽可能的大,那么,这个最大的最小距离是什么呢?
分析 : 面对这种安排的问题,遇到了两次了,一般都是考虑二分答案求最佳,这道题要求的答案是距离且是最大中的最小距离,那么我们去二分这个距离,面对每一个二分枚举出来的距离检查是否有大于这个距离的两点间距而且这样的间距等于或者超过C,如果有则继续往右界二分,否则向小的左界二分,很明显一开始的左右界是L = 0, R = MaxDis,MaxDis = 最右点 - 最左点,为了达到这个并且满足二分的单调特性,故我们需要对一开始给出的栅栏排个升序,至于如何检查是否有超过C个数满足条件的间距因为是排好序了,就很简单了,看代码即可!
#include<stdio.h> #include<algorithm> using namespace std; const int maxn = 1e5 + 5; int Location[maxn], n, c; bool OK(int dis) { int cnt = 1, st = Location[1]; for(int i=2; i<=n; i++){ if(Location[i] - st >= dis){ cnt++; st = Location[i]; if(cnt >= c) return true; } }return false; } int Solve() { int L = 0, R = Location[n]-Location[1], mid; while(L <= R){ mid = L + ((R-L)>>1); if(OK(mid)) L = mid + 1; else R = mid - 1; } return L - 1; } int main(void) { scanf("%d %d", &n, &c); for(int i=1; i<=n; i++) scanf("%d", &Location[i]); sort(Location+1, Location+1+n); printf("%d\n", Solve()); return 0; }