maximum shortest distance
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2385 Accepted Submission(s): 783
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
Recommend
zhouzeyong
题意:从平面中选K个点,使得这k个点中最近的两个点的距离尽可能的大。
解题思路:实在没想到竟然可以用最大团去做!太巧了!首先把所有点两两间的距离算出来,很容易想到答案就在这些距离中。所以我们可以二分答案,对于当前答案,把比这个长的边全部连起来生成图,如果该图的最大团比k大,那么成立。
这里坑爹,不能用朴素的最大团求法,不然会超时,要用Bron-Kerbosch算法求最大团,中间很好剪枝,速度极快。
#include <iostream>
#include <vector>
#include <map>
#include <math.h>
#include <algorithm>
#include <memory.h>
using namespace std;
struct point
{
double x;
double y;
int index;
point(int a, int b, int c)
{
x = a;
y = b;
index = c;
}
};
int n, k;
int G[55][55];
double dis[55][55];
int all[200][200]; //第j个极大团所包含的节点
int some[200][200];
int none[200][200];
vector<point> ps;
vector<double> ans;
//all集合记录的是当前极大团中已经加入的点
//some集合记录的是可能还能加入的点(也就是说可能与R集合中所有点都有边存在的点)
//none集合记录的是已经完成极大团计数的点(作用是判重)
bool dfs(int x, int an, int sn, int nn)
{
if (an >= k)//搜索到了答案
return 1;
if (an + sn < k)//剪枝
return 0;
int key = some[x][1];
for (int j = 1; j <= sn; j++)
{
int v = some[x][j];
int tsn = 0;
int tnn = 0;
//剪枝,与key相连的,必被搜索过
if (G[key][v])
continue;
for (int i = 1; i <= an; i++)
all[x + 1][i] = all[x][i];
all[x + 1][an + 1] = v;
for (int i = 1; i <= sn; i++)
if (G[v][some[x][i]])
some[x + 1][++tsn] = some[x][i];
for (int i = 1; i <= nn; i++)
if (G[v][none[x][i]])
none[x + 1][++tnn] = none[x][i];
if (dfs(x + 1, an + 1, tsn, tnn))
return 1;
some[x][j] = 0;
none[x][++nn] = v;
}
return 0;
}
bool judge(int m)
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (i != j)
if (dis[i][j] >= ans[m])
{
G[i][j] = 1;
}
else
{
G[i][j] = 0;
}
}
}
for (int i = 1; i <= n; i++)
some[1][i] = i;
if (dfs(1, 0, n, 0))
return 1;
else
return false;
}
int main()
{
int a, b;
while (~scanf("%d%d", &n, &k))
{
ps.clear();
for (int i = 1; i <= n; i++)
{
scanf("%d%d", &a, &b);
ps.push_back(point(a, b, i));
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (i != j)
{
dis[i][j] = sqrt((ps[i - 1].x - ps[j - 1].x) * (ps[i - 1].x - ps[j - 1].x) + (ps[i - 1].y - ps[j - 1].y) * (ps[i - 1].y - ps[j - 1].y));
ans.push_back(dis[i][j]);
//cout<<sqrt((ps[i - 1].x - ps[j - 1].x) * (ps[i - 1].x - ps[j - 1].x) + (ps[i - 1].y - ps[j - 1].y) * (ps[i - 1].y - ps[j - 1].y))<<endl;
}
}
}
sort(ans.begin(), ans.end());
int l = 0, r = unique(ans.begin(), ans.end()) - ans.begin();
while (l < r)
{
int m = (l + r) / 2;
if (judge(m))
{
l = m + 1;
}
else
r = m;
}
//cout<<l<<endl;
printf("%.2lf\n", ans[l - 1]);
}
return 0;
}