题目:codeforce 333-E. Summer Earnings
time limit per test9 seconds
Many schoolchildren look for a job for the summer, and one day, when Gerald was still a schoolboy, he also decided to work in the summer. But as Gerald was quite an unusual schoolboy, he found quite unusual work. A certain Company agreed to pay him a certain sum of money if he draws them three identical circles on a plane. The circles must not interfere with each other (but they may touch each other). He can choose the centers of the circles only from the n options granted by the Company. He is free to choose the radius of the circles himself (all three radiuses must be equal), but please note that the larger the radius is, the more he gets paid.
Help Gerald earn as much as possible.
Input
The first line contains a single integer n — the number of centers (3 ≤ n ≤ 3000). The following n lines each contain two integers xi, yi ( - 104 ≤ xi, yi ≤ 104) — the coordinates of potential circle centers, provided by the Company.
All given points are distinct.
Output
Print a single real number — maximum possible radius of circles. The answer will be accepted if its relative or absolute error doesn’t exceed 10 - 6.
Examples
inputCopy
3
0 1
1 0
1 1
outputCopy
0.50000000000000000000
inputCopy
7
2 -3
-2 -3
3 0
-3 -1
1 -2
2 -2
-1 0
outputCopy
1.58113883008418980000
题目大意:找到三个点,使得以三个点为圆心以相同半径画一个圆,同时这三个圆不相交,可相切。问能够画的最大的圆的半径是多少?
题目思路:
一开始看着有9000ms,所以直接暴力找三个点求出三边长然后最短边,找到的所有最短边的集合中最小的就是答案。奈何数据量太大,第四组就卡掉了!!!!
后来参照题解发现可以用bitset优化来解决该题。
具体思路:先求出(n2复杂度)所有的边的集合,因为要找的边是尽可能大中的较小的,所以现将所有边从大到小排序,然后依次放入,对于每一个点i都对应着一个二进制行(bitset),它的第j位为1,表示当前i与j的边已经放入,当放入新边时,如果这条边的两个顶点都和某一点相连的边已经放入,此时找到的三点就是可满足条件的最大,而将放入的边的一半就是答案(因为这是放入的边是最小的,同时也是没放入中最大的)。
了解bitset的两个操作:a.set(b)将a的第b为变为1,a.count()返回为1的位数。
code
#include<iostream>
#include<cstdio>
#include<bitset>
#include<cmath>
#include<algorithm>
#define N 3001
#define x first
#define y second
using namespace std;
struct Node{
int u,v;
double val;
}a[3001*3001];
pair<int,int>p[N];
bool cmp(Node a,Node b){
return a.val>b.val;
}
bitset<N>b[N];
int n;
int main()
{
cin>>n;
for(int i=1;i<=n;i++){
cin>>p[i].x>>p[i].y;
}
int cnt=0;
for(int i=1;i<=n;i++){
for(int j=1;j<i;j++){
a[++cnt]={i,j,sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y))};
}
}
sort(a+1,a+1+cnt,cmp);
for(int i=1;i<=cnt;i++){
int x=a[i].u,y=a[i].v;
if((b[x]&b[y]).count()){
printf("%.10lf",a[i].val/2);
return 0;
}
b[x].set(y);
b[y].set(x);
}
}