[湖大热身赛]Pesky Mosquitoes(求圆覆盖最大点数)

本文介绍了一种通过算法确定碗能覆盖的最大蚊子数量的方法。使用几何原理和枚举技术来寻找最佳位置,以覆盖尽可能多的目标。文章包含了完整的源代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Pesky Mosquitoes
Time Limit: 4000ms, Special Time Limit:10000ms, Memory Limit:65536KB
Total submit users: 8, Accepted users: 8
Problem 13239 : No special judgement
Problem description

Mosquitoes are relentless this time of year! They have absolutely ruined your attempt at a picnic and it is time to take your revenge. Unfortunately, you are not well equipped to ward off these pests. All you have got at your disposal is an empty bowl that previously held potato salad. As you glance down at the picnic table, you see a number of mosquitoes waiting idly for you to let your guard down. This is your chance to fight back.

Your task is to determine the maximum number of mosquitoes that can be trapped by quickly bringing down the inverted bowl onto the table. You will be provided with the diameter of the bowl and the exact location of each mosquito on the table. In this exercise you can assume that the mosquitoes are incredibly small and can simply be modeled as a point. A mosquito that lies exactly under the edge of the bowl is considered trapped.


Input

The first number in the input will be an integer 1 ≤ n ≤ 100 that denotes the number of mosquito- trapping scenarios that follow. A blank line comes at the beginning of each scenario. Then follows a line containing an integer 1 ≤ m ≤ 32 (the number of mosquitoes) and a real number 0 < d ≤ 200 (the diameter of the bowl). Each of the following m lines will specify the location of a mosquito in the form of real coordinates −100 ≤ x ≤ 100 and −100 ≤ y ≤ 100.


Output

For each scenario, you are to print the maximum number of mosquitoes that can be caught under the bowl in that scenario. You may assume that the answer would not change if the diameter of the bowl is increased by at most 10−5.


Sample Input
2
4 1.5
1.0 3.75
3.0 1.0
1.0 2.25
1.5 3.0
8 3.0
-1.0 3.0
-1.0 2.0
-2.0 1.0
0.0 1.0
1.0 0.0
1.0 -1.0
2.0 -2.0
3.0 -1.0
Sample Output
3
4

几何题:给出一个碗的直径,然后给出n个蚊子的位置,问这个碗能覆盖最多蚊子的数量。

覆盖最多,枚举两个蚊子肯定在圆上求圆心,就能覆盖最广。后来想到可能有一个蚊子的情况没有写,但是也过了,小问题。哦,后来不知道为什么用pow()会超时。。。淡淡的忧伤。。。

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<functional>
#define eps 1e-9
#include<vector>
#define pi acos(-1)
using namespace std;
const double PI = acos(-1.0);
int dcmp( double x ){ if( fabs(x) < eps ) return 0;else return x < 0?-1:1; }
struct point{
    double x,y;
    point( double x = 0,double y = 0 ):x(x),y(y){}
}node[112]; 
typedef point Vector;
struct segment
{
    point a,b;
	segment(){}
    segment(point _a,point _b){a=_a,b=_b;}
};
struct circle{
    point c; double r;  circle(){}
    circle(point _c, double _r):c(_c),r(_r) {}
    point  PPP(double a)const{return point(c.x+cos(a)*r,c.y+sin(a)*r);}
};
struct line{
    point p,v; double ang;
    line() {}
    line( const point &_p, const point &_v):p(_p),v(_v){ang = atan2(v.y, v.x);}
    inline bool operator < (const line &L)const{return  ang < L.ang;}
};
point operator + (point a,point b){return point( a.x + b.x,a.y + b.y );}
point operator - (point a,point b){return point( a.x - b.x,a.y - b.y );}
point operator * (point a,double b){return point( a.x*b,a.y*b );}
point operator / (point a,double b){ return point( a.x/b,a.y/b );}
bool  operator <  (const point &a, const point &b ){return  a.x <  b.x || (a.x == b.x && a.y < b.y );}
bool  operator == (const point &a, const point &b ){return (dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0 );}
bool  operator != (const point &a,const point &b ){return a == b?false:true;}

double Dot( point a,point b ){return a.x*b.x + a.y*b.y;} // 点到点的距离  //点积 ab=|a||b|cos@
double Length( point a ){return sqrt( Dot( a,a ) );}    // 向量长度
double Angle( point a,point b ){ return acos( Dot(a,b)/Length(a)/Length(b) );} // 两个向量的角度
double D_T_D(const double deg){ return deg/180.0*PI;}  //弧度转换成角度 
double dist(point p1,point p2)
{
    return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
// 向量旋转 rad 度数 rad>0逆时针,rad<0顺时针
point Rotate( point a, double rad ){
     return point( a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad) );
}
// 向量的 法线向量 的单位向量 ==向量逆时针旋转90度
point Normal( point a ){
     double L = Length(a); 
	 return point(-a.y/L,a.x/L);
}
// 叉积计算   a*b=|a||b|sin@;
double Cross( point a,point b ){
    return a.x*b.y - a.y*b.x;
}

//已知圆上亮点求圆心 
point get_cc(point p1,point p2,double r){
    point mid=point((p1.x+p2.x)/2,(p1.y+p2.y)/2);
    double angle=atan2(p1.x-p2.x,p2.y-p1.y);
    double d=sqrt(r*r-(dist(p1,mid)*dist(p1,mid)));
    return point(mid.x+d*cos(angle),mid.y+d*sin(angle));
}
point p[50];
int main(){
	int T,n,i,j,k;
	double r;
	scanf("%d",&T);
	while (T--){
		scanf("%d%lf",&n,&r);
		r=r*1.0/2;
		for (i=1;i<=n;i++)
			scanf("%lf%lf",&p[i].x,&p[i].y);
		int ans=0;
		for (i=1;i<n;i++)
			for (j=i+1;j<=n;j++){
				int s=0;
				point g=get_cc(p[i],p[j],r);
				for (k=1;k<=n;k++)
					if (dist(g,p[k])<=r) s++;
				if (ans<s) ans=s;
			}
		printf("%d\n",ans);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值