zoukankan      html  css  js  c++  java
  • HDU 1077 Catching Fish(计算几何,用单位圆围尽量多的点)

    Catching Fish

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


    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
     
    Author
    Ignatius.L
     
     
     
    简单的计算几何题。
    枚举两个点来确定圆心,然后求解。
    但是注意N==1的时候,一定要保证输出是1,这里WA了很久。
     
    两个程序,一个用结构体,一个用数组,用数组的要快很多。
     
     
    /*
    HDU 1077
    题意:给出一些点坐标,问有一个半径为1的圆,一次最多能圈多小个点;
    
    枚举两个点确定圆心,然后求解
    O(n^3)
    G++ 2515ms
    */
    #include<stdio.h>
    #include<math.h>
    #include<algorithm>
    #include<iostream>
    #include<iostream>
    using namespace std;
    
    const int MAXN=330;
    const double eps=1e-4;
    
    struct Point
    {
        double x,y;
    }point[MAXN];
    
    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 get_center_point(Point a,Point b)//根据两个点确定圆心,保证两点的距离不大于2,圆的半径为1
    {
        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);//圆心到中点的距离
        if(fabs(a.y-b.y)<1e-6)
        {
            center1.x=x0;
            center1.y=y0+d;
            center2.x=x0;
            center2.y=y0-d;
        }
        else
        {
            double tmp=atan(-(a.x-b.x)/(a.y-b.y));
            double dx=d*cos(tmp);
            double dy=d*sin(tmp);
            center1.x=x0+dx;
            center1.y=y0+dy;
            center2.x=x0-dx;
            center2.y=y0-dy;
        }
    }
    
    int main()
    {
        int T;
        int n;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);
            for(int i=0;i<n;i++)
              scanf("%lf%lf",&point[i].x,&point[i].y);
            int ans=1;//注意一个点的情况,所以初值应该给0,否则会一只wa的。
            for(int i=0;i<n;i++)
              for(int j=i+1;j<n;j++)
              {
                  if(dis(point[i],point[j])>2.0)continue;
                  get_center_point(point[i],point[j]);
                  int cnt=2;
                  for(int t=0;t<n;t++)
                    if(t!=i&&t!=j&&dis(point[t],center1)<1+eps)
                      cnt++;
                  if(cnt>ans)ans=cnt;
                  cnt=2;
                  for(int t=0;t<n;t++)
                    if(t!=i&&t!=j&&dis(point[t],center2)<1+eps)
                      cnt++;
                  if(cnt>ans)ans=cnt;
              }
            printf("%d\n",ans);
        }
        return 0;
    }
    /*
    HDU 1077
    题意:给出一些点坐标,问有一个半径为1的圆,一次最多能圈多小个点;
    
    枚举两个点确定圆心,然后求解
    O(n^3)
    用数组实现,更节约时间
    G++ 968ms
    
    */
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<iostream>
    #include<math.h>
    using namespace std;
    const int MAXN=330;
    const double eps=1e-4;
    
    double p[MAXN][2];
    double xx1,yy1,xx2,yy2;
    
    double dis(int i,int j)
    {
        return sqrt((p[i][0]-p[j][0])*(p[i][0]-p[j][0])+(p[i][1]-p[j][1])*(p[i][1]-p[j][1]));
    }
    
    void get_center_point(int a,int b)
    {
        double x0=(p[a][0]+p[b][0])/2;
        double y0=(p[a][1]+p[b][1])/2;
        double d=sqrt(1-((p[a][0]-p[b][0])*(p[a][0]-p[b][0])+(p[a][1]-p[b][1])*(p[a][1]-p[b][1]))/4);
        if(fabs(p[a][1]-p[b][1])<1e-6)
        {
            xx1=x0;
            yy1=y0+d;
            xx2=x0;
            yy2=y0-d;
        }
        else
        {
            double tmp=atan(-(p[a][0]-p[b][0])/(p[a][1]-p[b][1]));
            double dx=d*cos(tmp);
            double dy=d*sin(tmp);
            xx1=x0+dx;
            yy1=y0+dy;
            xx2=x0-dx;
            yy2=y0-dy;
        }
    }
    
    int main()
    {
        int T;
        int n;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);
            for(int i=0;i<n;i++)
               scanf("%lf%lf",&p[i][0],&p[i][1]);
            int ans=1;
            for(int i=0;i<n;i++)
              for(int j=i+1;j<n;j++)
              {
                  if(dis(i,j)>2.0)continue;
                  get_center_point(i,j);
                  int cnt=0;
                  for(int i=0;i<n;i++)
                    if(sqrt((p[i][0]-xx1)*(p[i][0]-xx1)+(p[i][1]-yy1)*(p[i][1]-yy1))<1+eps)
                      cnt++;
                  if(cnt>ans)ans=cnt;
                  cnt=0;
                  for(int i=0;i<n;i++)
                    if(sqrt((p[i][0]-xx2)*(p[i][0]-xx2)+(p[i][1]-yy2)*(p[i][1]-yy2))<1+eps)
                      cnt++;
                  if(cnt>ans)ans=cnt;
              }
            printf("%d\n",ans);
        }
        return 0;
    }
     
    人一我百!人十我万!永不放弃~~~怀着自信的心,去追逐梦想
  • 相关阅读:
    Nginx证书配置:tomcat证书jks文件转nginx证书.cet和key文件
    postgresql中实现按周统计详解
    symfony 初始化项目
    从零开始创建 symfony-cmf
    Installing Symfony project with PHP 7.3 version
    GIT Submodule的使用
    分享 koa + mysql 的开发流程,构建 node server端,一次搭建个人博客
    vue 响应式原理
    $nextTick 源码解析
    记一次webpack打包优化
  • 原文地址:https://www.cnblogs.com/kuangbin/p/2732091.html
Copyright © 2011-2022 走看看