二分-Aggressive cows


描述:农夫 John 建造了一座很长的畜栏,它包括N (2 <= N <= 100,000)个隔间,
这些小隔间依次编号为x1,...,xN (0 <= xi <= 1,000,000,000).但是,John的
C (2 <= C <= N)头牛们并不喜欢这种布局,而且几头牛放在一个隔间里,他们就要
发生争斗。为了不让牛互相伤害。John决定自己给牛分配隔间,使任意两头牛之间的
最小距离尽可能的大,那么,这个最大的最小距离是什么呢?
输入
第一行:空格分隔的两个整数N和C
第二行——第N+1行:分别指出了xi的位置
输出
每组测试数据输出一个整数,满足题意的最大的最小值,注意换行。
样例输入
5 3
1
2
8
4
9
样例输出
3

思路:我理解N值是告诉有几个x的值,x值可以理解为一个栅栏柱,使任意2头牛之间间隔
距离尽可能的大,求这个最大值。
第1种方法可以穷举遍历:Xn/C,x坐标的最大值除以C,得到距离D的最大值,也就是所有
的值不会超过这个值,所以可以从Xn/C开始遍历依次尝试这个距离,不符合就减1,如果符合
条件,则该值既是所求的最大值。考虑到Xn的最大值有1000000000,这样遍历会运算特别慢,
因此第二种方法,就是利用二分的思路来解决该问题。
第2种方法就是在取距离D的时候,利用了二分思想。
其实就是先假设一个距离D,然后从第一个坐标点开始,加上这个距离D,如果第2个坐标
点小于该值,则遍历第3个坐标点,如果第3个坐标点与第1个坐标点的距离大于D,那么说明可以
放下1头牛,则从第3个坐标点再加上距离D,类似第1点一样,判断与第4个点的距离是否大于
距离D,如果点之间的距离符合D的,则sum加1,遍历结束后,如果sum大于C,那么说明该距离D
可以放下C头牛,否则不能放入C头牛。

Python算法实现:
 1 N,C = 0,0
 2 
 3 def Ok(d,listSorted):
 4     sum,firstValue = 1 ,listSorted[0]
 5     for i in range(1,len(listSorted)):
 6         #当前i位置的值与前面点的值距离大于等于v,说明这个距离可以放下一头牛
 7         if listSorted[i] - firstValue >= d:
 8             firstValue = listSorted[i]
 9             sum+=1
10     #如果可以放下的数量大于等于牛的数量,说明这个距离能满足要求放完牛
11     if sum >= C :
12         return True
13     else:
14         return False
15 
16 def main():
17     list1 = list(map(int,input().split(" ")))
18     list2 = []
19     global N,C
20     N = list1[0]
21     C = list1[1]
22     for i in range(N):
23         temp = int(input())
24         list2.append(temp)
25     list2.sort()
26     low, high, mid = list2[0], list2[N-1], 0
27     #当相减的距离是1的时候,则遍历结束
28     while(high - low > 1):
29         d = int((low+high)/2)
30         #true,说明这个距离d符合要求,可以再尝试把d的距离变大,看是否符合放下C头牛
31         if Ok(d,list2):
32             #当最后这个low的赋值,既是所求的值
33             low = d
34         #false,说明该距离太大,所以把mid赋值给high,让距离D的区间缩小
35         else:
36             high = d
37     print("%d"%low)
38 if __name__ == "__main__":
39     main()





原文地址:https://www.cnblogs.com/an-wl/p/12835515.html