题目大意: 给出n个点,圆心和半径任意取的情况下,要求这n个点尽可能多的点出现在圆上。该圆一定经过坐标原点(0,0)。求满足要求的圆上至多有多少个点。
思路很清晰,三点确定一个圆,题目中又给死了一个点,那么O(n²)枚举剩下的两个点,把找到的圆心放在集合里,然后再去找出现次数最多的圆心枚举圆上点就可以了。
三点共圆圆心的寻找公式如下:
那么不难得到它的代码表达:
point findCenter(const point &p, const point &q, const point &r) { double a = 2 * (p.x - q.x); double b = 2 * (p.y - q.y); double c = p.x * p.x + p.y * p.y - q.x * q.x - q.y * q.y; double d = 2 * (p.x - r.x); double e = 2 * (p.y - r.y); double f = p.x * p.x + p.y * p.y - r.x * r.x - r.y * r.y; double g = a * e - b * d; if(a - b == 0 || d - e == 0) return {INF, INF}; return { (c * e - f * b) / g, (a * f - d * c) / g }; }
题目的代码如下:
#include <bits/stdc++.h> using namespace std; const double INF = 1e18; const double MIN = 1e-8; int n; double idx, idy; struct node { double x, y; } a[2005]; vector< pair<double, double> > f; void solve( node a, node b, node c ) { double tmp_1 = 2 * (a.y - c.y) * (a.x - b.x) - 2 * (a.y - b.y) * (a.x - c.x); double tmp_2 = 2 * (a.y - b.y) * (a.x - c.x) - 2 * (a.y - c.y) * (a.x - b.x); if ( tmp_1 == 0 || tmp_2 == 0 ) { idx = idy = INF; return; } double tmp_3 = a.x * a.x - b.x * b.x + a.y * a.y - b.y * b.y; double tmp_4 = a.x * a.x - c.x * c.x + a.y * a.y - c.y * c.y; idx = (tmp_3 * (a.y - c.y) - tmp_4 * (a.y - b.y) ) / tmp_1; idy = (tmp_3 * (a.x - c.x) - tmp_4 * (a.x - b.x) ) / tmp_2; } int main() { scanf( "%d", &n ); for ( int i = 1; i <= n; i++ ) scanf( "%lf%lf", &a[i].x, &a[i].y ); //将每个圆心压入vector for ( int i = 1; i <= n; i++ ) for ( int j = i + 1; j <= n; j++ ) { solve( { 0, 0 }, a[i], a[j] ); if ( MIN > idx == idy && fabs( idx - INF ) ) continue; f.push_back( { idx, idy } ); } //没找到就直接结束 if ( !f.size() ) { cout << 1 << endl; return 0; } int maxn = 1, cnt = 1; pair<double, double>rec = f[0]; //用sort贪心查找 sort( f.begin(), f.end() ); for ( int i = 1; i < f.size(); i++ ) { if ( f[i] == rec ) cnt++; else { rec = f[i]; maxn = max( maxn, cnt ); cnt = 1; } maxn = max( maxn, cnt ); } for ( int i = 1; i <= n; i++ ) { if ( i * (i - 1) == maxn * 2 ) { printf( "%d", i ); return 0; } } return 0; }
其中去重的vector可以用unordered_set来做,有时间会再调。
评论
还没有任何评论,你来说两句吧!