2020/7/14
ここでは2つの方法が使用されます。
- 既知の回答の円は原点と交差するため、円上の点と原点の間の最終的な垂直二等分線は円の中心と交差する必要があります。n点と原点の間の垂直二等分線が計算されます。n*(n -1)/ 2つの交点。これらのn *(n-1)/ 2点の中で、特定の点が最も多く現れる回数を見つけます。回数が答えです(垂直二等分線の同じ交差は、円の中心が一致し、円が原点を通過することを意味するため、同じ円内にあります) )。
交点を導出するプロセスは複雑ではありません。最後に、同時方程式を2回解いて、交点の座標(xi、yi)を解きます(xを垂直二等分線に入れてyを見つけないでください。これは、より面倒です)。
コード:
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<b;i++)
using namespace std;
const int maxn=2e3+9;
typedef pair<double,double> pdd;
int n;
double x[maxn],y[maxn];
map<pdd,int> res;
int main(){
scanf("%d",&n);
rep(i,0,n) scanf("%lf%lf",x+i,y+i);
int ans=0;
rep(i,0,n) {
res.clear();
rep(j,i+1,n){
if(x[i]*y[j]==x[j]*y[i]) continue;
double d=x[i]*y[j]-x[j]*y[i],d1=x[i]*x[i]+y[i]*y[i],d2=x[j]*x[j]+y[j]*y[j];
double X=(y[i]*d2-y[j]*d1)/d,Y=(x[i]*d2-x[j]*d1)/d;
ans=max(ans,++res[{
X,Y}]);
}
}
printf("%d\n",ans+1);
}
- 2番目のアプローチはソリューションによって与えられます:
コード:
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long LL;
const double eps = 1e-15;
const int N = 2010;
int X[N], Y[N];
double A[N];
int Cross(int lhs, int rhs) {
// 向量叉积
return X[lhs] * Y[rhs] - X[rhs] * Y[lhs];
}
int Dis2(int lhs, int rhs) {
// 两点欧氏距离的平方
int dx = X[lhs] - X[rhs], dy = Y[lhs] - Y[rhs];
return dx * dx + dy * dy;
}
double GetCosAngle2(int i, int j) {
// Oi对角的cos值
int a2 = Dis2(0, i), b2 = Dis2(i, j), c2 = Dis2(0, j);
return (double)(b2 + c2 - a2) / 2 / sqrt(b2) / sqrt(c2);
}
int main()
{
int n, ans = 1;
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d%d", X + i, Y + i);
for (int i = 1; i <= n; i++) {
int cnt = 0;
for (int j = 1; j <= n; j++) if (Cross(i, j) < 0) A[++cnt] = GetCosAngle2(i, j);
sort(A + 1, A + cnt + 1);
for (int l = 1, r; l <= cnt; l = r) {
for (r = l; fabs(A[l] - A[r]) < eps && r <= cnt; r++);
ans = max(ans, r - l + 1);
}
}
printf("%d\n", ans);
return 0;
}