2020牛客暑期多校训练营 第二场 B Boundary 计算几何 圆 已知三点求圆心
LINK:Boundary
计算几何确实是弱项 因为好多东西都不太会求 没有到很精通的地步。
做法很多,先说官方题解
其实就是枚举一个点 P 然后可以发现 再枚举一个点 然后再判断有多少个点在圆上显然会超时。
直接考虑求出所有点和\(O,P\)的夹角 因为同弧所对圆周角相等 最后统计有多少个角度相等来做。
一个误区是 两个对称的圆上的点被算在一起了 此时强制利用 第三个点在所在直线的左侧/右侧来消除影响。
正确性显然。复杂度\(n^2\cdot logn\)
一个比较好想好写的做法:
枚举到第三个点的时候就不能再统计有多少个点在这个圆上了 然后 考虑答案的圆的圆心一定是被重复计算出次数最多的。
所以可以得到某个圆心被计算次数最多的数量 反推出点数即可。
一个难点 已知三点求圆心 这好像是一个模板 不过推导需要利用 克莱姆法则及矩阵行列式的知识来推 这我肯定式推不出来滴 而且公式挺难背的!~
code
//#include<bits\stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 10000000000000000ll
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define gc(a) scanf("%s",a+1)
#define rep(p,n,i) for(RE int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define fep(n,p,i) for(RE int i=n;i>=p;--i)
#define vep(p,n,i) for(RE int i=p;i<n;++i)
#define pii pair<int,int>
#define mk make_pair
#define RE register
#define P 1000000007
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-6
#define sq sqrt
#define S second
#define F first
#define mod 1000000007
#define V vector
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
RE int x=0,f=1;RE char ch=getc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
return x*f;
}
const int MAXN=2010;
int n,flag;db w1,w2;
struct wy
{
db x,y;
}t[MAXN];
V<pair<db,db> >g;
int pd(db x,db y){return fabs(x-y)<=EPS;}
inline void calc(wy a,wy b,wy c)
{
flag=0;
db D1=2*(a.y-c.y)*(a.x-b.x)-2*(a.y-b.y)*(a.x-c.x);
db D2=2*(a.y-b.y)*(a.x-c.x)-2*(a.y-c.y)*(a.x-b.x);
if(pd(D1,0)||pd(D2,0)){flag=1;return;}
db W1=pf(a.x)-pf(b.x)+pf(a.y)-pf(b.y);
db W2=pf(a.x)-pf(c.x)+pf(a.y)-pf(c.y);
w1=(W1*(a.y-c.y)-W2*(a.y-b.y))/D1;
w2=(W1*(a.x-c.x)-W2*(a.x-b.x))/D2;
}
int main()
{
//freopen("1.in","r",stdin);
get(n);
rep(1,n,i)get(t[i].x),get(t[i].y);
rep(1,n,i)rep(i+1,n,j)
{
calc((wy){0,0},t[i],t[j]);
if(flag)continue;
g.pb(mk(w1,w2));
}
if(g.size()==0){puts("1");return 0;}
sort(g.begin(),g.end());
int mx=1,cnt=1;pair<db,db>ww=g[0];
vep(1,g.size(),i)
{
if(pd(ww.F,g[i].F)&&pd(ww.S,g[i].S))++cnt,mx=max(mx,cnt);
else ww=g[i],cnt=1;
}
int cc=(1+(int)sqrt(1+1.0*8*mx))/2;
put(cc);return 0;
}