SPOJ SP898 TRANSMIT - Transmitters 题解

Description

在平面直角坐标系中给出一个圆的圆心和半径,给出若干个平面上的点。问以给定点为圆心,以给定长度为半径的半圆最多可以覆盖平面上的多少个点。

Solution

半圆在坐标系中可以任意旋转,可能的角度有无限个,显然无法枚举。但是稍作分析,我们可以发现,若当前情况下半圆的直径上没有一个点,那么我们将这个半圆旋转直到直径上包含了至少一个点,那么答案一定不会更劣。也就是说,在保证覆盖点数最多的情况下一定至少存在一种情形,使得直径上至少有一个点。因此,我们只是需要枚举哪个点在直径上即可。

具体来说,我们可以首先删除那些到圆心的距离大于半径的点。之后枚举每个点在直径上的情况。由于此时已经将直径所在直线确定下来了,我们可以用叉积求出有多少个点在直径的同侧(包含直径),并更新答案。

时间复杂度 \(O(Tn^2)\),其中 \(T\) 为数据组数。

Code

#include<bits/stdc++.h>
using namespace std;
const int N=1010;
struct Point{
	double x,y;
}a[N];
double dist(Point p1,Point p2)
{
	return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
double cross(Point a,Point b,Point c)//叉积
{
	return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}
int main()
{
	double r;
	while(scanf("%lf%lf%lf",&a[0].x,&a[0].y,&r)!=EOF&&r>=0)
	{
		int T,n=0;
		scanf("%d",&T);
		while(T--)
		{
			double x,y;
			scanf("%lf%lf",&x,&y);
			if(dist(a[0],Point{x,y})<=r) a[++n]={x,y};
		}
		int cnt,ans=0;
		for(int i=1;i<=n;i++)
		{
			cnt=0;
			for(int j=1;j<=n;j++)
				if(cross(a[0],a[i],a[j])>=0) 
					cnt++;
			ans=max(ans,cnt);
		}
		printf("%d\n",ans);
	}
	return 0;
}
posted @   __Star_Sky  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
点击右上角即可分享
微信分享提示