Luogu P1742 minimum circle cover

Keywords: iOS

Problem surface

Given N points, let's draw the smallest circle that contains all the points.

Analysis

This problem is actually to find out a circle determined by three points, which can contain all other points.

There is a close relationship with three points in a circle. First, three points in a circle.
There are two cases of three points in a circle: three points are collinear or non collinear, two farthest points are collinear to form diameter, and non collinear to form a triangle circumscribed circle
Considering the circumscribed circle situation, it is easy to find the center of circle by using sine theorem, in fact, the difficulty is to find the center of circle, that is, to express the coordinates of the outer center by using the coordinates of three vertices of triangle.

The three points in the code here refer to the calculation of the center of a circle This article.
In fact, there are other methods, such as the intersection of the center of two lines, the intersection of the center of a vector perpendicular to the center of a circle, etc., but it is relatively easy to use the three-point coordinate of a triangle to directly implement the code

Let's talk about the minimum circle covering. In fact, we use the mathematical induction method. If we have covered the first i points, we will try to create a circle to cover i+1 points.

Consider the following steps:
1. It is known that 1 ~ i-1 points have been covered by circle Ci − 1c {i-1} Ci − 1. Now, i want to add the ith point and let it also be covered by circle
2. If the ith point is already in the circle Ci − 1c {I-1} Ci − 1, then the next circle Ci=Ci − 1c_i = C {I-1} Ci=Ci − 1, and go back to the first step to continue
3. If not, a new circle needs to be constructed with 1 ~ i points. First, the newly added point i needs to be on the edge of the circle (critical case), which also determines a point on the circle
4. Round t1t {1} T1 with the first point and the ith point. If there is a point J (J < i) that is not in t1t {1} T1, it is taken as the second point on the edge of CIC {ICI.
5. Circle T2T ﹤ 2t2 with two points i and j. in the same four steps, find the point K (k < j < i) that is not in the circle T2T ﹤ 2t2. If it exists, then K is the third point on the edge of circle CIC ﹤ ICI.
6. Now the three points of i j k are all on the circle CIC ﹣ ICI, and it can be proved that CIC ﹣ ICI contains all points from 1 to I, so we use three points to construct CIC ﹣ ICI, and go back to 1 to continue the iteration.
Iteration to CNCN ends

This seems to be a three-layer loop, but in fact, it expects complexity O(n), but in order to prevent data from being inappropriate, we need to scramble the given n points before processing, which can be realized by random_shuffle()

Code

#include <iostream>
#include<algorithm>
#include<string.h>
#include<string>
#include<math.h>
#include<iomanip>
using namespace std;
struct Point
{
	double x, y;
	Point() {}
	Point(double x,double y):x(x),y(y){}
};//Save point structure
inline double dis(Point &p1, Point &p2)//Distance between two points
{
	return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));

}
inline double sqr(double x) { return x * x; }//square
class min_circle {
private:
	Point p[100005];
	int n;
public:
	Point center;//Represents the center of the circle constructed every time
	double r;//Represents the radius of each construction
	void init(int n)
	{
		this->n = n;
		for (int i = 0; i < n; i++)cin >> p[i].x >> p[i].y;
		random_shuffle(p, p + n);//Disruption, avoid card
	}

	void circular()//Construction circle sequence
	{
		r = 0, center = p[0];
		for (int i = 1; i < n; i++)//Try to determine if the ith point is not in the circle. If it is, enter the next point. If it is not, create a circle with p[i] on the edge
			if (dis(center, p[i]) - r > 1e-8)//p[i] outside the circle made before
			{
				r=dis(p[0],p[i])/2;//Take p[0] and p[i] as diameter to make a circle, find out the point p[j] outside the circle, as the second point on the edge of this circle
				center.x = (p[0].x + p[i].x) / 2;
				center.y= (p[0].y + p[i].y) / 2;
				for (int j = 0; j < i; j++)
				{
					if (dis(center, p[j]) - r > 1e-8)//We found this kind of j outside the circle
					{
						r = dis(p[i], p[j]) / 2;//p[i] and p[j] are the final points on the edge of the circle constructed in this round. Take these two as the diameter to construct a circle, and try to find the k point outside
						center.x = (p[i].x + p[j].x) / 2;
						center.y = (p[i].y + p[j].y) / 2;
						for (int k = 0; k < j; k++)
						{
							if (dis(center, p[k]) - r > 1e-8)//Find this kind of k
							{
								center = build_circle(p[i], p[j], p[k]);//It is found that p[i],p[j],p[k] are all on the edge of the circle constructed in this round, and the circle is determined
								r = dis(center, p[i]);
							}
						}
					}
				}
			}
	}

	Point build_circle(Point a, Point b, Point c) {//Three point making
		double a1, a2, b1, b2, c1, c2;
		Point ans;
		a1 = 2 * (b.x - a.x), b1 = 2 * (b.y - a.y),
			c1 = sqr(b.x) - sqr(a.x) + sqr(b.y) - sqr(a.y);
		a2 = 2 * (c.x - a.x), b2 = 2 * (c.y - a.y),
			c2 = sqr(c.x) - sqr(a.x) + sqr(c.y) - sqr(a.y);
		if (fabs(a1-0.0)<1e-8) {
			ans.y = c1 / b1;
			ans.x = (c2 - ans.y * b2) / a2;
		}
		else if (fabs(b1-0)<1e-8) {//Because there are two kinds of denominators, the two cases are specially judged
			ans.x = c1 / a1;
			ans.y = (c2 - ans.x * a2) / b2;
		}
		else {
			ans.x = (c2 * b1 - c1 * b2) / (a2 * b1 - a1 * b2);
			ans.y = (c2 * a1 - c1 * a2) / (b2 * a1 - b1 * a2);
		}
		return ans;
	}
}MC;
int main()
{
	ios::sync_with_stdio(false);
	int n;
	cin >> n;
	MC.init(n);//Reading and randomization, disruption
	MC.circular();
	cout << fixed << setprecision(10) << MC.r << endl << MC.center.x << " " << MC.center.y;
	return 0;
}
Published 38 original articles, won praise 0, visited 1244
Private letter follow

Posted by lachild on Sat, 15 Feb 2020 20:04:58 -0800