2020牛客暑期多校第二场 B-Boundary

题目点击这里
给你一个二维平面外加n(n<2000)个点,问你最多能找到几个点和原点(0,0)共圆。
错误思路:一开始是想先枚举一个点为直径,再找剩下的点中能直径形成直角的点。但是共圆的点不一定一定要存在着能形成直径的点,因此考虑不全。
正确做法:
1.可以向题解一样用圆周角来找
2.通过任意找两点,分别连接他们与原点,然后再在连接的直线上做中垂线,两条中垂线的交点即为圆心,最后判断哪个点成为圆心的次数最多即为我们所找的原,然后在判断最多可以从多大的n中(也就是我们最后求得答案)找两个点来满足要求。

找圆心的过程就是求解方程组:

在这里插入图片描述
参考:https://blog.csdn.net/weixin_43269437/article/details/107327887?%3E

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 2e3+7;
vector< pair<int,int> >P;//点 
vector< pair<double,double> >C;//可能的圆心 

ll getD(ll a,ll b,ll c,ll d){
    
    
	return a*d-b*c;
}
 
int main()
{
    
    
	int n;
	P.resize(2007);
	scanf("%d",&n);
	int x,y;
	for(int i = 1;i <= n;i ++){
    
    
		scanf("%d%d",&x,&y);
		P[i] = make_pair(x,y);//存对用make_pair 
	}
	for(int i = 1;i <= n-1;i ++){
    
    
		for(int j = i+1;j <= n;j ++){
    
    
			int x1 = P[i].first,y1 = P[i].second;
			int x2 = P[j].first,y2 = P[j].second;
			// 克拉默法则解方程组 
			ll a11 = 2*x1,a12 = 2*y1,b1 = x1*x1+y1*y1;
			ll a21 = 2*x2,a22 = 2*y2,b2 = x2*x2+y2*y2;
			ll D = getD(a11,a12,a21,a22);
			if(D == 0) continue;
			ll D1 = getD(b1,a12,b2,a22);
			ll D2 = getD(a11,b1,a21,b2);
			//printf("%d %d %d\n",D,D1,D2);
			C.push_back(make_pair((double)D1/D , (double)D2/D ));//圆心可能的解 
		}
	}
	sort(C.begin(),C.end());
	int maxx = 0;
	for(int i = 0;i < C.size();){
    
    
		int j = i;
		while(j < C.size()&&C[j] == C[i]) j++;
		maxx = max(maxx,j-i);
		i = j;
	}
	//cout<<maxx<<endl; 
	int ans = 0;
	for(int i = 1;i < MAXN;i ++){
    
    
		if((i-1)*i/2 <= maxx)//这个n可能是合法的点的个数
			ans = max(ans,i); 
	}
	printf("%d\n",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45672411/article/details/107381240