2020牛客暑期多校訓練營 第二場 B Boundary 計算幾何 圓 已知三點求圓心
阿新 • • 發佈:2020-07-14
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; }