牛客多校2—— Boundary (计算几何)
题意:
给出 n 个点,需要我们选择一个经过原点的圆,使得这个圆经过尽可能多的点,输出最多可以经过多少个点
思路:
三点不共线的点确定一个圆 O点已经确定,O(n)枚举另一个点P,O(n)枚举第三个点 ,这样三点就可以确定一个圆心,每次都取圆心出现最多的次数。
注意枚举的时候排除掉三点共线的情况。
代码:
#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math") #pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native") #pragma GCC optimize(2) #include<bits/stdc++.h> using namespace std; #define ll long long #define I_int ll typedef pair<int,int> PII; typedef pair<double,double>PDD; inline ll read() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } char F[200]; inline void out(I_int x) { if (x == 0) return (void) (putchar('0')); I_int tmp = x > 0 ? x : -x; if (x < 0) putchar('-'); int cnt = 0; while (tmp > 0) { F[cnt++] = tmp % 10 + '0'; tmp /= 10; } while (cnt > 0) putchar(F[--cnt]); //cout<<" "; } const int maxn=500000+100; double x[maxn],y[maxn]; map<PDD,ll>mp; int main(){ int n=read(); for(int i=1;i<=n;i++) scanf("%lf%lf",&x[i],&y[i]); ll res=0; for(int i=1;i<=n;i++){///枚举点P mp.clear(); for(int j=i+1;j<=n;j++){ if(x[j]*y[i]-y[j]*x[i]==0) continue; //三点共线 PDD tmp; tmp.first=((y[j]-y[i])*y[i]*y[j]-x[i]*x[i]*y[j]+x[j]*x[j]*y[i])/(x[j]*y[i]-x[i]*y[j]); tmp.second= ((x[j]-x[i])*x[i]*x[j]-y[i]*y[i]*x[j]+y[j]*y[j]*x[i])/(y[j]*x[i]-y[i]*x[j]); res=max(res,++mp[tmp]); } } out(res+1); return 0; }
参考博客: http://blog.sina.com.cn/s/blog_71726b130101dx6u.html
https://blog.csdn.net/weixin_42868863/article/details/107382515