Boundary

链接:https://ac.nowcoder.com/acm/contest/5667/B
来源:牛客网

题目描述

Given n{n}n points in 2D plane. Considering all circles that the origin point (0,0){(0, 0)}(0,0) is on their boundries, find the one with the maximum given points on its boundry. Print the maximum number of points.

输入描述:

The first line contains one integer n (1≤n≤2000)n~(1 \leq n \leq 2000)n (1≤n≤2000), denoting the number of given points.
Following n{n}n lines each contains two integers x,y (∣x∣,∣y∣≤10000)x, y~(|x|,|y| \leq 10000)x,y (∣x∣,∣y∣≤10000), denoting a given point (x,y){(x, y)}(x,y).
It's guaranteed that the points are pairwise different and no given point is the origin point.

输出描述:

Only one line containing one integer, denoting the answer.

示例1

输入

复制 4 1 1 0 2 2 0 2 2

4
1 1
0 2
2 0
2 2

输出

复制 3

3

说明

Considering circle (x−1)2+(y−1)2=2(x-1)^2+(y-1)^2=2(x−1)2+(y−1)2=2, we can see that the origin point is on its boundry and that there are 3 given points (0,2),(2,0),(2,2){(0,2),(2,0),(2,2)}(0,2),(2,0),(2,2) on its boundry.

题意: 原点默认, 给你一堆点。 然后画出的圆肯定要过原点,

思路:因为三点确定圆(这里我是去网上找板子的,因为之前就做计算几何的题), 所以枚举两个点。然后记录所有的圆心。

TLE:如果对所有圆心去看剩下的所有点是不是满足改圆心的半径,那么一共是O(n^3)的

优化:比如我们有四个点在一个圆上,那么因为题目给了原点,所以我们任取另外两个点就能形成这个圆,但是同时,虽然枚举的两点不同,最后出来的却是一个圆心,也就是说在这个情况下,我们算出来有C(4个取2个)的那么多相同的圆心。那假如有M个在一个圆上,我们sort一遍,然后统计圆心重合最多的时候数量是多少个(假如ans个)。然后再看哪个数能满足C(m个取2个)==ans;即答案

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=2e3+10;
typedef long long LL;
double getx(double x1,double y1,double x2,double y2,double x3,double y3)
{
    double a=((y2-y1)*(y3*y3-y1*y1+x3*x3-x1*x1)-(y3-y1)*(y2*y2-y1*y1+x2*x2-x1*x1))/(2.0*((x3-x1)*(y2-y1)-(x2-x1)*(y3-y1)));
    return a;
}
double gety(double x1,double y1,double x2,double y2,double x3,double y3)
{
    double b=((x2-x1)*(x3*x3-x1*x1+y3*y3-y1*y1)-(x3-x1)*(x2*x2-x1*x1+y2*y2-y1*y1))/(2.0*((y3-y1)*(x2-x1)-(y2-y1)*(x3-x1)));
    return b;
}
double x[maxn],y[maxn];
vector< pair<double,double> >v;
int main(void)
{
  cin.tie(0);std::ios::sync_with_stdio(false);
  LL n;cin>>n;
  for(LL i=1;i<=n;i++) cin>>x[i]>>y[i];
  for(LL i=1;i<n;i++)
  {
    for(LL j=i+1;j<=n;j++)
    {
        if(y[i]*x[j]==y[j]*x[i]) continue;//三点共线 
        double a=getx(0.0,0.0,x[i],y[i],x[j],y[j]);
        double b=gety(0.0,0.0,x[i],y[i],x[j],y[j]);
        double r=sqrt(a*a+b*b);
        
        v.push_back(make_pair(a,b));
    }
  }
  sort(v.begin(),v.end());

  if(v.size()==0)
  {
  	cout<<1<<endl;return 0;
  }
  LL sum=1; LL ans=1;
  for(int i=0;i<v.size();++i)
  {	
	double a=v[i].first;
    double b=v[i].second;
    double c=v[i+1].first;
    double d=v[i+1].second;
    if(fabs(c-a<1e-10&&fabs(d-b)<1e-10)) sum++,ans=max(sum,ans);
	else sum=1; 
  } 
 for(LL i=1;i<=n ;i++)
 {
 	if(i*(i-1)==2*ans)  	
	 {
	 	cout<<i<<endl;
	 	break;
	 }
 }
return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值