1. 程式人生 > 實用技巧 >2020牛客暑期多校訓練營 第二場 B Boundary 計算幾何 圓 已知三點求圓心

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