HDU--1077--Catching Fish--计算几何

Catching Fish

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1361    Accepted Submission(s): 522


Problem Description
Ignatius likes catching fish very much. He has a fishnet whose shape is a circle of radius one. Now he is about to use his fishnet to catch fish. All the fish are in the lake, and we assume all the fish will not move when Ignatius catching them. Now Ignatius wants to know how many fish he can catch by using his fishnet once. We assume that the fish can be regard as a point. So now the problem is how many points can be enclosed by a circle of radius one.

Note: If a fish is just on the border of the fishnet, it is also caught by Ignatius.
 

Input
The input contains several test cases. The first line of the input is a single integer T which is the number of test cases. T test cases follow.
Each test case starts with a positive integer N(1<=N<=300) which indicate the number of fish in the lake. Then N lines follow. Each line contains two floating-point number X and Y (0.0<=X,Y<=10.0). You may assume no two fish will at the same point, and no two fish are closer than 0.0001, no two fish in a test case are approximately at a distance of 2.0. In other words, if the distance between the fish and the centre of the fishnet is smaller 1.0001, we say the fish is also caught.
 

Output
For each test case, you should output the maximum number of fish Ignatius can catch by using his fishnet once.
 

Sample Input
  
  
4 3 6.47634 7.69628 5.16828 4.79915 6.69533 6.20378 6 7.15296 4.08328 6.50827 2.69466 5.91219 3.86661 5.29853 4.16097 6.10838 3.46039 6.34060 2.41599 8 7.90650 4.01746 4.10998 4.18354 4.67289 4.01887 6.33885 4.28388 4.98106 3.82728 5.12379 5.16473 7.84664 4.67693 4.02776 3.87990 20 6.65128 5.47490 6.42743 6.26189 6.35864 4.61611 6.59020 4.54228 4.43967 5.70059 4.38226 5.70536 5.50755 6.18163 7.41971 6.13668 6.71936 3.04496 5.61832 4.23857 5.99424 4.29328 5.60961 4.32998 6.82242 5.79683 5.44693 3.82724 6.70906 3.65736 7.89087 5.68000 6.23300 4.59530 5.92401 4.92329 6.24168 3.81389 6.22671 3.62210
 

Sample Output
  
  
2 5 5 11
不难的一道计算几何的问题,贴图如下。dyx
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=310;
const double wyx=1e-4;
//表示输入的两个坐标。
struct point
{
    double x,y;
}dyx[N];
//求解两点之间的距离。
double dis(point a,point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
//接下来用两个点来确定圆心的坐标。圆心的坐标有上下两个。
point center1,center2;//定义上下两个圆心。
void center_point(point a,point b)
{
    //以传入的两个点为圆心作单位圆,两个圆的两个交点即为所求圆心。
    //首先取两点连线的中点的坐标。
    double x0=(a.x+b.x)/2;
    double y0=(a.y+b.y)/2;
    //求出圆心到两点连线中点的距离。
    double d=sqrt(1-((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y))/4);
    //求出d的距离之后,要分情况进行讨论。
    //此处有一个需要注意的点。进行浮点数的比对时,判断俩数是否相等,不能直接==0,在精度上有一定的偏差。
    //if (disc == 0.0) 时,disc不一定精确地等于0,也许会等于0.000001。
    //为了避免浮点数比较上的误差,就要设定一个误差范围,也就是(-1e-6, 1e-6)这个范围内
    //如果disc落在这个范围内,就认为其等于0了。
    if(fabs(a.y-b.y)<1e-6)
    //即两个点位于同一y轴线上。
    {
        center1.x=x0;
        center1.y=y0+d;
        center2.x=x0;
        center2.y=y0-d;
    }
    else
    //如果不是的话,说明两点不在同一条线上
    {
        //注意atan里面要加负号。
        double rad=atan(-(a.x-b.x)/(a.y-b.y));//求出所需要的角的弧度,此处要证明一下两角相等.
        //atan函数求得是反正切的值。
        //sin,cos,操作的都是弧度值。
        double dx=d*cos(rad);
        double dy=d*sin(rad);
        center1.x=x0+dx;
        center1.y=y0+dy;
        center2.x=x0-dx;
        center2.y=y0-dy;
    }
}
int main()
{
    int T;//输入的T组数据。
    cin>>T;
    int n;//接下来有n个点。
    while(T--)
    {
        int ans=1;//进行输出的答案,但是要考虑到只有一个点的情况。
        cin>>n;
        for(int i=0;i<n;i++)
        {
            cin>>dyx[i].x>>dyx[i].y;
        }
        for(int i=0;i<n;i++)
            for(int j=i+1;j<n;j++)
        //都是在同一个数组内寻找两个点确定圆心,自己不和自己匹配,1-2&&2-1是一样的。
        {
            //两点距离大于2,不进行比对。
            if(dis(dyx[i],dyx[j])>2.0) continue;
            int cnt=2;//两点确定的圆心,这两个点肯定包含在了这个圆内。
            center_point(dyx[i],dyx[j]);
            for(int p=0;p<n;p++)
            if(p!=i&&p!=j&&dis(center1,dyx[p])<1+wyx)
            cnt++;
            if(cnt>ans)
            ans=cnt;
            cnt=2;
            for(int p=0;p<n;p++)
            if(p!=i&&p!=j&&dis(center2,dyx[p])<1+wyx)
            cnt++;
            if(cnt>ans)
            ans=cnt;
        }
        cout<<ans<<endl;
    }
 return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值