题目链接:点击打开链接
大致题意:给出N个不同的点,让你找出一个点P使得其到至少⌈N/2⌉个点的距离均为R
思路:先解决较简单情形,比如N=1,2时可以考虑在所给点中随便选一个点,取距离为0即符合题意
而N=3,4时则不妨取第一个点和第二个点的中点,然后距离取两者到其中点的距离
然后N>=5,则P点至少要到其中三个点距离相同
显然,如果这三点共线,是达不到上述要求的
而题目保证至少存在这样一个P,所以若三个点在⌈N/2⌉个点中,其必不共线,那么P显然为该三点的外心。
所以本题即枚举这样的三点,然后判断其外心作为P是否符合题意即可
关键问题就在这。如果暴力枚举,搜索,有C(N,3)个可能,然而题目中1<=N<=10^5,这样显然是大大超时的。
怎么办?
胆子大一点,用随机方法去枚举,解决问题。由于每个点在这⌈N/2⌉个点中的概率大致为1/2,取到的三个点在其中的概率大致为1/8,也就是说平均下来8次就能取到符合题意的三个点。这样下来,8轮判断,时间是在接受范围内的,用这种方法便能通过此题
扫描二维码关注公众号,回复:
294099 查看本文章

代码如下:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.DecimalFormat;
import java.util.Random;
import java.util.StringTokenizer;
class Reader{
static BufferedReader reader;
static StringTokenizer tokenizer;
static void init(InputStream input)
{
reader=new BufferedReader(new InputStreamReader(input));
tokenizer=new StringTokenizer("");
}
static String next() throws IOException{
while (!tokenizer.hasMoreTokens())
tokenizer=new StringTokenizer(reader.readLine());
return tokenizer.nextToken();
}
static int nextInt() throws IOException {
return Integer.parseInt(next());
}
static double nextDouble() throws IOException{
return Double.parseDouble(next());
}
}
class Point {
double x,y;
/**
* @param x
* @param y
*/
public Point(double x, double y) {
super();
this.x = x;
this.y = y;
}
/**
*
*/
public Point() {
super();
// TODO Auto-generated constructor stub
}
}
public class Main {
static Random random;
static int p1,p2,p3,t,n,k,maxn,cnt;
static double x[],y[];
static double mx,my,r,nowr;
static Point points[];
static DecimalFormat dec=new DecimalFormat("0.000");
static double dist(Point a,Point b)
{
double xsqr=(a.x-b.x)*(a.x-b.x);
double ysqr=(a.y-b.y)*(a.y-b.y);
return Math.sqrt(xsqr+ysqr);
}
static boolean oneline(Point a,Point b,Point c)
{
double x1=a.x-c.x;
double y1=a.y-c.y;
double x2=b.x-c.x;
double y2=b.y-c.y;
double res=x1*y2-x2*y1;
if (Math.abs(res)<1e-6) return true;
return false;
}
static Point waixin(Point a,Point b,Point c)
{
double a1=b.x-a.x,b1=b.y-a.y,c1=(a1*a1+b1*b1)/2;
double a2=c.x-a.x,b2=c.y-a.y,c2=(a2*a2+b2*b2)/2;
double d=a1*b2-a2*b1;
return new Point(a.x+(c1*b2-c2*b1)/d,a.y+(a1*c2-a2*c1)/d);
}
static void deal() {
if (n==1)
System.out.println(dec.format(x[1])+" "+dec.format(y[1])+" 0");
else if (n<=4)
{
mx=(x[1]+x[2])/2;
my=(y[1]+y[2])/2;
r=dist(points[1],points[2])/2;
System.out.println(dec.format(mx)+" "+dec.format(my)+" "+dec.format(r));
}
else
{
if (n%2==1) k=n/2+1;
else k=n/2;
while (true)
{
p1=random.nextInt(n)+1;
p2=random.nextInt(n)+1;
p3=random.nextInt(n)+1;
if ((p1!=p2)&&(p2!=p3)&&(p1!=p3))
if (!oneline(points[p1],points[p2], points[p3]))
{
Point p=waixin(points[p1],points[p2],points[p3]);
r=dist(points[p1],p);
cnt=0;
for (int i=1;i<=n;i++)
{
nowr=dist(points[i], p);
if (Math.abs(nowr-r)<1e-6)
cnt++;
if (cnt+n-i<k) break;
if (cnt>=k) break;
}
if (cnt>=k) {
System.out.println(dec.format(p.x)+" "+dec.format(p.y)+" "+dec.format(r));
return;
}
}
}
}
}
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
Reader.init(System.in);
random=new Random();
t=Reader.nextInt();
maxn=100000;
x=new double[maxn+1];
y=new double[maxn+1];
points=new Point[maxn+1];
for (int casenum=1;casenum<=t;casenum++)
{
n=Reader.nextInt();
for (int i=1;i<=n;i++)
{
x[i]=Reader.nextDouble();
y[i]=Reader.nextDouble();
points[i]=new Point(x[i],y[i]);
}
deal();
}
}
}