Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 9797 | Accepted: 4865 |
Description
Input
Output
Sample Input
5 3 1 2 8 4 9
Sample Output
3
Hint
最大化最小值
农夫约翰搭了一间有n间牛舍的小屋。牛舍排在一条线上第i号牛舍在xi的位置。但是他的m头牛对小屋很不满意,因此经常互相攻击。约翰为了防止牛之间互相伤害,因此决定把每头牛都放在离其他牛尽可能远的牛舍。也就是要最大化最近的两头牛之间的距离
分析:
我们定义C(d):=可以安排牛的位置是的最近的两头牛的距离不小于d
那么问题就变成了求满足C(d)的最大值的d。另外,最近的间距不小于d也可以说成是所有牛的间距都不小于d,因此就有
C(d) = 可以安排牛的位置使得任意的牛的间距都不小于d
这个问题的判断使用贪心法便可以非常容易的求解。
1. 对牛舍的位置x进行排序
2. 把第一头牛放入x0的牛舍
3. 如果第i头牛放入了xj的话,第i+ 1头牛就要放入满足xj + d <= xk的最小的xk中
对x的排序只需在最开始时进行一次就可以了,每一次判断对每头牛最多进行一次处理,因此复杂度是O(N)。
//最大化最小值 #include <cstdio> #include <algorithm> using namespace std; const int maxn = 100000 + 10; const int INF = 100000000; int n, m; int x[maxn]; bool C(int d) { int last = 0; for (int i = 1; i < m; i++){ int crt = last + 1; while (crt < n && x[crt] - x[last] < d){ crt++; } if (crt == n) return false; last = crt; } return true; } void solve() { //从最开始对x数组排序 sort(x, x + n); //初始化解的存在范围 int lb = 0, ub = INF; while (ub - lb > 1){ int mid = (lb + ub) / 2; if (C(mid)) lb = mid; else ub = mid; } printf("%d\n", lb); } int main() { while (scanf("%d%d", &n, &m) != EOF){ for (int i = 0; i < n; i++){ scanf("%d", &x[i]); } solve(); } return 0; }