HDU3585 最大团+二分

maximum shortest distance

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1777    Accepted Submission(s): 589


Problem Description
There are n points in the plane. Your task is to pick k points (k>=2), and make the closest points in these k points as far as possible.
 

 

Input
For each case, the first line contains two integers n and k. The following n lines represent n points. Each contains two integers x and y. 2<=n<=50, 2<=k<=n, 0<=x,y<10000.
 

 

Output
For each case, output a line contains a real number with precision up to two decimal places.

 

 

Sample Input
3 2
0 0
10 0
0 20
 

 

Sample Output
22.36
 

 

Author
alpc50

 题意:

给出n个点,问从中取哪k个点使得这k个点中每两个点之间的距离的最小值最大,输出这个距离。

代码:

//求最小值最大一般用二分。此题求出每两点之间的距离,然后二分距离,两点之间的距离大于等于此二分值的点之间连线,
//重新建图,求新图的最大团是否大于等于k。这道题可以不直接二分距离,给距离排序二分下标即可。套最大团模板。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int n,best,m;
int mp[52][52],num[52];
double dis[2502],tmp[52][52],x[52],y[52];
bool dfs(int s[],int sum,int cnt)
{
    if(sum==0){
        if(cnt>best){
            best=cnt;
            return 1;
        }
        return 0;
    }
    int t[102];
    for(int i=0;i<sum;i++){
        if(cnt+(sum-i)<=best) return 0;
        if(cnt+num[s[i]]<=best) return 0;
        int k=0;
        for(int j=i+1;j<sum;j++){
            if(mp[s[i]][s[j]]) t[k++]=s[j];
        }
        if(dfs(t,k,cnt+1)) return 1;
    }
    return 0;
}
bool Maxt(int M)
{
    //if(n<=0) return 0;
    int s[102];
    best=0;
    memset(mp,0,sizeof(mp));
    for(int i=0;i<n;i++) 
        for(int j=i+1;j<n;j++)
            if(tmp[i][j]>=dis[M]) mp[i][j]=mp[j][i]=1;
    for(int i=n-1;i>=0;i--){
        int k=0;
        for(int j=i+1;j<n;j++){
            if(mp[i][j]) s[k++]=j;
        }
        dfs(s,k,1);
        num[i]=best;
        if(best>=m) return true;
    }
    return false;
}
int main()
{
    while(~scanf("%d%d",&n,&m)){
        int cnt=0;
        for(int i=0;i<n;i++){
            scanf("%lf%lf",&x[i],&y[i]);
            tmp[i][i]=0;
            for(int j=0;j<i;j++)
                dis[cnt++]=tmp[i][j]=tmp[j][i]=((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
        }
        sort(dis,dis+cnt);
        int ans=0;
        int L=0,R=cnt-1,M;
        while(L<=R){
            M=(L+R)/2;
            if(Maxt(M)) {L=M+1;ans=M;}
            else R=M-1;
        }
        printf("%.2lf\n",sqrt(dis[ans]));
    }
    return 0;
}

 

posted @ 2017-02-02 18:28  luckilzy  阅读(279)  评论(0编辑  收藏  举报