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;
}
标签:
解题报告
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App