首页 > 代码库 > 路由器安置

路由器安置

一条街道安装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;
}

 

路由器安置