简单思路
一个圆套中了几个点,如果不断缩小这个圆,那么最终的结果有两种
- 有两个点卡住了这个圆,且这两点一定是直径
- 有三个或者三个以上的点卡住了这个圆,圆心在这三个点围成的三角形的外接圆圆心。
因此我们枚举两点作为直径,或者枚举三个点作为圆的内接三角形,求这个三角形的外接圆圆心即可。
最后对这些圆进行判断一共围住了几个点。
复杂度大概\(O(n^3+n^4)\)
参考代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
#define endl '\n'
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define rep(i, a, b) for (int i = (a); i < (b); ++i)
#define Forget_that return
#define f(x, y) (x * x + y * y)
#define Just_go 0
#define Endl endl
#define ednl endl
#define eldn endl
#define dnel endl
#define enndl endl
#define Ednl endl
#define Edml endl
#define llmax 9223372036854775807
#define intmax 2147483647
#define f(x, y) (x * x + y * y)
struct point
{
ld x;
ld y;
point(ld xx = 0, ld yy = 0)
{
x = xx;
y = yy;
}
} arr[100000];
point fun(const point &p1, const point &p2, const point &p3) //求三角形外接圆圆心
{
ld x1 = p1.x, y1 = p1.y, x2 = p2.x, y2 = p2.y, x3 = p3.x, y3 = p3.y;
ld d1 = f(x2, y2) - f(x1, y1), d2 = f(x3, y3) - f(x2, y2);
ld fm = 2 * ((y3 - y2) * (x2 - x1) - (y2 - y1) * (x3 - x2));
ld ans_x = ((y3 - y2) * d1 - (y2 - y1) * d2) / fm;
ld ans_y = ((x2 - x1) * d2 - (x3 - x2) * d1) / fm;
return point(ans_x, ans_y);
}
struct circle
{
ld x;
ld y;
ld r;
int cnt;
circle(ld xx, ld yy, ld rr)
{
x = xx;
y = yy;
r = rr;
cnt = 0;
}
};
ld dis(const point &a, const point &b)
{
return sqrtl(1.0L * (a.x - b.x) * (a.x - b.x) + 1.0L * (a.y - b.y) * (a.y - b.y));
}
ld dis(const circle &a, const point &b)
{
return sqrtl(1.0L * (a.x - b.x) * (a.x - b.x) + 1.0L * (a.y - b.y) * (a.y - b.y));
}
bool isIn(const circle &x, const point &b)
{
ld dist = dis(x, b);
if (dist < x.r)
return true;
if (abs(dist - x.r) < 1e-7)
return true;
return false;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n;
cin >> n;
_rep(i, 1, n)
{
ll xtemp;
ll ytemp;
cin >> xtemp >> ytemp;
arr[i].x = xtemp;
arr[i].y = ytemp;
}
vector<circle> vec;
for (int i = 1; i <= n; i++) //枚举直径,构造圆
{
for (int j = i + 1; j <= n; j++)
{
vec.push_back(circle(0.5L * (arr[i].x + arr[j].x), 0.5L * (arr[i].y + arr[j].y), 0.5L * dis(arr[i], arr[j])));
}
}
for (int i = 1; i <= n; i++) //枚举三角形,求外接圆
{
for (int j = i + 1; j <= n; j++)
{
for (int k = j + 1; k <= n; k++)
{
point temp = fun(arr[i], arr[j], arr[k]); //外接圆圆心
vec.push_back(circle(temp.x, temp.y, dis(temp, arr[i])));
}
}
}
for (auto it = vec.begin(); it != vec.end(); it++)
{
for (int i = 1; i <= n; i++)
{
if (isIn(*it, arr[i])) //判断圆中包含多少个点
it->cnt++;
}
}
vector<ld> ans(n + 10, 1e14);
for (auto it = vec.begin(); it != vec.end(); it++) //写题解的时候发现这里应该判断一下,因为有可能不存在圆能恰好围住x个点,但是存在圆能恰好围住x+1个点。建议加强数据,也有可能我写题解的时候想多了。
ans[it->cnt] = min(it->r, ans[it->cnt]);
for (int i = 2; i <= n; i++)
{
for (int j = 1; j < i; j++)
{
cout << fixed << setprecision(10) << ans[i] << endl;
}
}
Forget_that Just_go;
}
标签:Provincial,cnt,Contest,题解,ll,xtemp,vec,ytemp
From: https://www.cnblogs.com/acidbarium/p/18682673