题目链接
解题思路
给出L个位置,要在L个位置中选出S个位置建造base stations。可以把问题简化成在L个点中选S个点,在所有的选择方案中,S个点之间得最短距离最大,我们用
m
i
n
_
d
i
s
min\_dis
min_dis 表示这个距离。
m
i
n
_
d
i
s
min\_dis
min_dis的范围是在0~L个位置中最大的值。
现在我们一步步来看,首先假设
l
l
l 的值是0;
r
r
r 是L个位置中最大的值;定义
m
m
m,
m
=
(
l
+
r
)
/
2
m = (l + r) / 2
m=(l+r)/2,我们来确定
m
m
m 是否满足:在L个点中可以选到S个点,使得这S个点之间的距离都不小于
m
m
m,这个判断只需要一个迭代就行了。
判断完成后,分为两种情况。如果
m
m
m 可以满足,那么
m
≤
m
i
n
_
d
i
s
≤
r
m \le min\_dis \le r
m≤min_dis≤r,令
l
=
m
l = m
l=m;如果
m
m
m 不满足,那么
l
≤
m
i
n
_
d
i
s
<
m
l \le min\_dis \lt m
l≤min_dis<m,令
r
=
m
r = m
r=m。根据这个性质,我们可以二分的求出
m
i
n
_
d
i
s
min\_dis
min_dis,要注意的一点是当
m
m
m 不满足时,
m
i
n
_
d
i
s
min\_dis
min_dis 是小于
m
m
m 而不是小于等于,因为已经判定不存在
m
m
m,使得选定的S个点之间的距离都不小于
m
m
m,所以可以断定
m
i
n
_
d
i
s
min\_dis
min_dis 小于
m
m
m。所以每次
l
l
l 总是满足要求的,而
r
r
r 却不满足要求(除了一种特殊情况,后面再讨论)
源代码如下:
#include<iostream>
#include<algorithm>
#define NUM 100050
using namespace std;
int L[NUM];
int n, s;
bool solve(int m){
int pos = 0;
int c = s-1;
for(int i=1; i<n; i++){
if(L[i] - L[pos] >= m){
pos = i;
c--;
if(c == 0) return true;
}
}
return false;
}
int main() {
while(cin>>n>>s, n||s){
for(int i=0; i<n; i++){
cin>>L[i];
}
sort(L, L+n);
int l = 0;
int r = L[n-1];
int m;
while(r-l!=1){
m = (l + r)>>1;
if(solve(m)){
l = m;
}
else {
r = m;
}
}
cout << l << endl;
}
return 0;
}
一种特殊情况是 r r r 一直没变,只有 l l l 改变,且只选择2个点,最小的点的值是0,那么这样 l l l 的值不再是最终结果, r r r 才是,这种情况上面的程序不能处理,但是在计蒜客却能AC,可能是数据不行吧。