太阳王的安排(二分搜索)

题号:NC21446
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述 

太阳王葛温在结束了古龙的时代后,建立了亚诺尔隆德,然而数量众多的银骑士如何安置让他有些心烦。在某次用阳光枪打猎古龙之后,葛温想到了办法,他在亚诺尔隆德中开辟了一大片地方用来当作银骑士的居所,但是由于事务繁忙,他只好把工作安排给他的儿子——太阳长男手里,并嘱咐他尽快安排好,不然把他发配去天天猎古龙。你能帮帮太阳长男吗? 

你可以把可安置区域看做一条一维坐标轴(从原点0开始到正无穷),在坐标值为整数的点上可以安排m个银骑士,但因为条件所限,可以安置银骑士的位置只有n个。由于银骑士们荣誉感太强,如果他们住的太近,就会展开决斗,试图割下对方的耳朵。所以你要让每个银骑士之间的最小距离尽可能地大来避免发生冲突。 

输入描述:

第一行为一个正整数T,代表数据组数。对于每组数据,第一行有两个整数n和m(2<=n<=100000,2<=m<=n)。n代表可以安置区域的数量,m代表需要被安置的银骑士数量。接下来的n行中,每一行有一个非负整数ai(ai<=10^9),表示可以安置区域的位置。

输出描述:

输出一个整数,为把所有银骑士全部安排好后,他们之间的最小距离最大值。

示例1

输入

复制

1
5 3
1
2
8
4
9

输出

复制

3

说明

对于样例,你可以把3个银骑士分别安置在1、4、8的位置上,这样他们之间的最小距离为3。其他的安排方案,他们之间的最小距离都小于等于3,所以3是最大的最小距离
#include<iostream>
#include<string>
#include<cmath>
using namespace std;
const int mod=1e9+7;
typedef long long  ll;

//void dfs(int a,int b){
//    if(b==k) {
//        ans++;
//        return;
//    }
//    for(int i=a+1;i<=m*n;i++){
//        int x=(i-1)/m+1;
//        int y=(i-1)%m+1;
//        if(s[x-1][y]==0&&s[x][y-1]==0){
//            s[x][y]=1;
//            dfs(i,b+1);
//            s[x][y]=0;
//        }
//    }
//}
//bool is(long long  x){
//    if(x<=2) return true;
//    for(long long  i=2;i*i<x;i++){
//        if(x%i==0) return false;
//    }
//    return true;
//}

//ll f(int x){
//    if(x<2) return x;
//    return (f(x/2)+f(x%2));
//}
//bool is(int x){
//    int t=h/x;
//    if(h%x!=0) t++;
//    if(c-p*t<0){
//        return false;
//    }
//    return true;
//}
//int sum;
//ll ff(ll n){
//    if(n==1) return 1;
//
//    return n*ff(n-1);
//}
//ll f(int n){
//
//    while(n){
//        sum+=n%10;
//        n/=10;
//    }
//    if(n>=10){
//        f(sum);
//    }
//    return sum;
//}

//const int MAXN = 305;
//const int INF = 0x3f3f3f3f;
//
//int love[MAXN][MAXN];   // 记录每个妹子和每个男生的好感度
//int ex_girl[MAXN];      // 每个妹子的期望值
//int ex_boy[MAXN];       // 每个男生的期望值
//bool vis_girl[MAXN];    // 记录每一轮匹配匹配过的女生
//bool vis_boy[MAXN];     // 记录每一轮匹配匹配过的男生
//int match[MAXN];        // 记录每个男生匹配到的妹子 如果没有则为-1
//int slack[MAXN];        // 记录每个汉子如果能被妹子倾心最少还需要多少期望值
//
//int N;
//
//
//bool dfs(int girl)
//{
//    vis_girl[girl] = true;
//
//    for (int boy = 0; boy < N; ++boy) {
//
//        if (vis_boy[boy]) continue; // 每一轮匹配 每个男生只尝试一次
//
//        int gap = ex_girl[girl] + ex_boy[boy] - love[girl][boy];
//
//        if (gap == 0) {  // 如果符合要求
//            vis_boy[boy] = true;
//            if (match[boy] == -1 || dfs( match[boy] )) {    // 找到一个没有匹配的男生 或者该男生的妹子可以找到其他人
//                match[boy] = girl;
//                return true;
//            }
//        } else {
//            slack[boy] = min(slack[boy], gap);  // slack 可以理解为该男生要得到女生的倾心 还需多少期望值 取最小值 备胎的样子【捂脸
//        }
//    }
//
//    return false;
//}
//
//int KM()
//{
//    memset(match, -1, sizeof match);    // 初始每个男生都没有匹配的女生
//    memset(ex_boy, 0, sizeof ex_boy);   // 初始每个男生的期望值为0
//
//    // 每个女生的初始期望值是与她相连的男生最大的好感度
//    for (int i = 0; i < N; ++i) {
//        ex_girl[i] = love[i][0];
//        for (int j = 1; j < N; ++j) {
//            ex_girl[i] = max(ex_girl[i], love[i][j]);
//        }
//    }
//
//    // 尝试为每一个女生解决归宿问题
//    for (int i = 0; i < N; ++i) {
//
//        fill(slack, slack + N, INF);    // 因为要取最小值 初始化为无穷大
//
//        while (1) {
//            // 为每个女生解决归宿问题的方法是 :如果找不到就降低期望值,直到找到为止
//
//            // 记录每轮匹配中男生女生是否被尝试匹配过
//            memset(vis_girl, false, sizeof vis_girl);
//            memset(vis_boy, false, sizeof vis_boy);
//
//            if (dfs(i)) break;  // 找到归宿 退出
//
//            // 如果不能找到 就降低期望值
//            // 最小可降低的期望值
//            int d = INF;
//            for (int j = 0; j < N; ++j)
//                if (!vis_boy[j]) d = min(d, slack[j]);
//
//            for (int j = 0; j < N; ++j) {
//                // 所有访问过的女生降低期望值
//                if (vis_girl[j]) ex_girl[j] -= d;
//
//                // 所有访问过的男生增加期望值
//                if (vis_boy[j]) ex_boy[j] += d;
//                // 没有访问过的boy 因为girl们的期望值降低,距离得到女生倾心又进了一步!
//                else slack[j] -= d;
//            }
//        }
//    }
//
//    // 匹配完成 求出所有配对的好感度的和
//    int res = 0;
//    for (int i = 0; i < N; ++i)
//        res += love[ match[i] ][i];
//
//    return res;
//}

int m,n;
int a[10005];
int check(int mid){
    int res=1;
    int p=a[1];
    for(int i=2;i<=n;i++){
        if(a[i]-p>=mid){
            res++;
            p=a[i];
        }
    }
    return res>=m;
}
int main()
{
    int t;
    cin>>t;
    while (t--)  {
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            cin>>a[i];
        }
        sort(a+1,a+n+1);
        int l=0;
        int r=a[n]-a[1];
        while(l<=r){
            int mid=(r+l)/2;
            if(check(mid))
            {
                l=mid+1;
            }
               else{
                r=mid-1;
            }
        }
        cout<<l-1<<endl;
    }
    return 0;
}

上一篇:hasattr,getattr和setattr


下一篇:hasattr、getattr、setattr反射