hdu6242(随机化)

题目链接:点击打开链接

大致题意:给出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轮判断,时间是在接受范围内的,用这种方法便能通过此题


代码如下:

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();
		}
	}

}

猜你喜欢

转载自blog.csdn.net/lixiaomu2/article/details/80260152