一条街道安装WIFI,需要放置M个路由器。整条街道上一共有N户居民,分布在一条直线上,每一户居民必须被至少一台路由器覆盖到。现在的问题是所有路由器的覆盖半径是一样的,我们希望用覆盖半径尽可能小的路由器来完成任务,因为这样可以节省成本。
输入格式:
输入文件第一行包含两个整数M和N,以下N行每行一个整数Hi表示该户居民在街道上相对于某个点的坐标。
输出格式:
输出文件仅包含一个数,表示最小的覆盖半径,保留一位小数。
样例输入:
2 3
1
3
10
样例输出:
1.0
题解:
二分直径,每次找到没有被覆盖的点
#include<iostream> #include<iomanip> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; int m,n; long long a[110000]; bool check(long long w) { int temp1=0,temp2=1; while((temp1=upper_bound(a,a+n,a[temp1]+w)-a)<n) //返回第一个比a[temp1]+w大的位置,如果覆盖不了,就继续+w,反之位置++,以此来找到刚好满足条件的数 if(++temp2>m) return 0; return 1; } double find() { int l=0, r=a[n-1]-a[0]; while(l<r) //二分,判断直径的关键条件 { int mid=(l+r)/2; if(check(mid)) r=mid; //未满足循环条件,说明此数过大,要找到的数在左边 else l=mid+1; //设置的路由器大于m个,要找到的数在右边 } return l*1.0/2; } int main() { ios::sync_with_stdio(false); cout<<setiosflags(ios::fixed)<<setprecision(1); cin>>m>>n; for(int i=0;i<n;i++) cin>>a[i]; sort(a,a+n); cout<<find()<<endl; return 0; }