2020牛客暑期多校训练营(第二场)Boundary
题目链接
https://ac.nowcoder.com/acm/contest/5667/B
题目大意
给你 N 个点的坐标 , 要求你找到一个圆使得原点在这个圆边上且其它尽可能多的点在圆的边上
求这个圆包含的点的个数 ( N <= 2000 )
解题思路
三个点可以构造一个圆 ( 三点贡献的情况除外 )
那么已知圆经过了原点 , 则剩下两个点我们可以暴力枚举
然后以这三点求出这个圆的圆心坐标 , 并统计圆心坐标出现的次数
枚举完任意两点后我们要找的圆的圆心坐标即是出现次数最多的坐标
ans = 圆心出现次数 + 1
AC_Code
#include<bits/stdc++.h> using namespace std; #define lb long double const int N = 2e3 + 10; int n , ans; lb x[N] , y[N]; map<pair<lb , lb> , int> mp; bool check(int i , int j) { if(x[i] * y[j] - x[j] * y[i]) return true; return false; } pair<lb , lb> get_xy(int i , int j) { lb nx = ((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]); lb ny = ((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]); return make_pair(nx , ny); } signed main() { ios::sync_with_stdio(false) , cin.tie(0) , cout.tie(0); cin >> n; for(int i = 1 ; i <= n ; i ++) cin >> x[i] >> y[i]; for(int i = 1 ; i <= n ; i ++) { mp.clear(); for(int j = i + 1 ; j <= n ; j ++) { if(!check(i , j)) continue ; int now = ++ mp[get_xy(i , j)]; ans=max(ans , now); } } cout << ans + 1 << '\n'; return 0; }
凡所不能将我击倒的,都将使我更加强大