maximum shortest distance
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1386 Accepted Submission(s): 469
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
Source
此题是一个最大团的变形问题,题目给出k,和n个点,求出n个点之间的距离,让你求出最小的lim,两点距离大于lim算连通,使得最大团的顶点数不小于k。距离方面可以用二分的思想来优化,而最大团直接套小编给出的最大团模板即可。
#include <math.h>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=50+10;
int g[maxn][maxn],dp[maxn],stk[maxn][maxn],mx;
void dfs(int n, int ns, int dep)
{
if (ns == 0)
{
if (dep > mx) mx = dep;
return ;
}
int i,j,k,p,cnt;
for(i=0; i<ns; i++)
{
k = stk[dep][i];
cnt = 0;
if(dep + n - k <= mx) return ;
if(dep + dp[k] <= mx) return ;
for(j=i+1; j<ns; j++)
{
p = stk[dep][j];
if(g[k][p]) stk[dep+1][cnt++] = p;
}
dfs(n, cnt, dep+1);
}
return ;
}
int clique(int n)
{
int i,j,ns;
for(mx=0, i=n-1; i>=0; i--)
{
for(ns=0, j=i+1; j<n; j++)
if(g[i][j]) stk[1][ns++] = j;
dfs(n, ns, 1);
dp[i] = mx;
}
return mx;
}
int x[maxn],y[maxn],n,k;
double arc[maxn][maxn],dis[maxn*maxn];
bool check(double lim)
{
int i,j;
memset(g,0,sizeof(g));
for(int i=0; i<n; i++)
for(int j=i+1; j<n; j++)
if(arc[i][j] >= lim)
g[i][j] = g[j][i] = 1;
if(clique(n) >= k) return true;
else return false;
}
int main()
{
int i,j,cnt;
while(scanf("%d%d",&n,&k)!=EOF)
{
for(i=0; i<n; i++) scanf("%d%d",&x[i],&y[i]);
cnt=0;
for(i=0; i<n; i++)
{
arc[i][i] = -1;
for(j=i+1; j<n; j++)
{
arc[i][j] = sqrt((double)((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])));
dis[cnt++] = arc[j][i] = arc[i][j];
}
}
sort(dis,dis+cnt);
int l=0,r=cnt-1,mid,ans;
while(l<=r)
{
mid = (l+r)>>1;
if(check(dis[mid]))
{
ans = mid;
l = mid+1;
}
else r = mid-1;
}
printf("%.2lf\n",dis[ans]);
}
return 0;
}