zoukankan      html  css  js  c++  java
  • 最近点对

    Quoit Design

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


    Problem Description
    Have you ever played quoit in a playground? Quoit is a game in which flat rings are pitched at some toys, with all the toys encircled awarded.
    In the field of Cyberground, the position of each toy is fixed, and the ring is carefully designed so it can only encircle one toy at a time. On the other hand, to make the game look more attractive, the ring is designed to have the largest radius. Given a configuration of the field, you are supposed to find the radius of such a ring.

    Assume that all the toys are points on a plane. A point is encircled by the ring if the distance between the point and the center of the ring is strictly less than the radius of the ring. If two toys are placed at the same point, the radius of the ring is considered to be 0.
     
    Input
    The input consists of several test cases. For each case, the first line contains an integer N (2 <= N <= 100,000), the total number of toys in the field. Then N lines follow, each contains a pair of (x, y) which are the coordinates of a toy. The input is terminated by N = 0.
     
    Output
    For each test case, print in one line the radius of the ring required by the Cyberground manager, accurate up to 2 decimal places. 
     
    Sample Input
    2 0 0 1 1 2 1 1 1 1 3 -1.5 0 0 0 0 1.5 0
     
    Sample Output
    0.71 0.00 0.75
     

     小弟功力不够,代码是由网上下载的,今后的路还有很长要走啊!

      1 /*
      2 *最近点对的问题
      3 */
      4 
      5 #include <iostream>
      6 #include<cstdio>
      7 #include <algorithm>
      8 #include <cmath>
      9 using namespace std;
     10 const int SIZE = 100005;
     11 const int L = -1;
     12 const int R = 1;
     13 
     14  typedef struct
     15 {
     16     int index;
     17     double x;
     18     double y;   /*用于记录坐标点*/
     19 }coord;
     20 
     21 coord num[SIZE], c[SIZE]/*用作辅助数组*/;
     22 
     23 double getDistance(coord &bi1, coord &bi2)  /*求得两点之间的距离*/
     24 {
     25     return sqrt(pow(bi1.x - bi2.x, 2.0) + pow(bi1.y - bi2.y, 2.0));
     26 }
     27 
     28 bool cmpx(coord bi1, coord bi2)
     29 {
     30     if (bi1.x == bi1.x)
     31         return bi1.y < bi2.y;
     32     else
     33     return bi1.x < bi2.x;
     34 }
     35 
     36 bool cmpy(coord bi1, coord bi2)
     37 {
     38     if (bi1.y == bi2.y)
     39         return bi1.x < bi2.x;
     40     else
     41         return bi1.y < bi2.y;
     42 }
     43 
     44 inline double min(double &bi1, double &bi2, double &bi3)
     45 {
     46     double minLength;
     47     minLength = bi1 > bi2 ? bi2 : bi1;
     48     minLength = minLength > bi3 ? bi3 : minLength;
     49     return minLength;
     50 }
     51 
     52 inline double minDist(double &bi1, double &bi2)
     53 {
     54     if (bi1 > bi2)
     55         return bi2;
     56     return bi1;
     57 }
     58 
     59 
     60 double divide_conquer(int low, int high) /*分治法求最小距离*/
     61 {
     62     double dis;
     63     int count = high - low;
     64     if (count == 0)
     65     {
     66         return 0;
     67     }
     68     else if (count == 1)  /*两个数*/
     69     {
     70         dis = getDistance(num[low], num[high]);
     71     }
     72     else if (count == 2)  /*三个数*/
     73     {
     74         double temp1, temp2, temp3;
     75         temp1 = getDistance(num[low], num[low + 1]);
     76         temp2 = getDistance(num[low + 1], num[high]);
     77         temp3 = getDistance(num[low], num[high]);
     78         dis = min(temp1, temp2, temp3);
     79     }
     80     else   /*大于三个数的情况*/
     81     {
     82         double leftmin, rightmin, min;
     83         int mid = (low + high) / 2;
     84         int p = 0;
     85         int i, j;
     86 
     87         leftmin = divide_conquer(low, mid);  /*求得左边部分的最小值*/
     88         rightmin = divide_conquer(mid + 1, high);  /*求得右边部分的最小值*/
     89         dis = minDist(leftmin, rightmin);
     90 
     91         /*下面从所有坐标点中找出所有x在leftCoord到rightCoord之间的点*/
     92         for (i = low; i <= mid; i++)
     93         {
     94             double leftCoord = num[mid].x - dis;
     95             if (num[i].x >= leftCoord)
     96             {
     97                 c[p].index = L;  /*标识属于左边部分*/
     98                 c[p].x = num[i].x;
     99                 c[p].y = num[i].y;
    100                 p++;
    101             }
    102         }
    103         for ( ; i <= high; i++)
    104         {
    105             double rightCoord = num[mid].x + dis;
    106             if (num[i].x <= rightCoord)
    107             {
    108                 c[p].index = R;  /*标识属于右边部分*/
    109                 c[p].x = num[i].x;
    110                 c[p].y = num[i].y;
    111                 p++;
    112             }
    113         }
    114         sort(c, c + p, cmpy);   /*找到的点再从小到大按照y排序一次*/
    115         for (i = 0; i < p; i++)
    116         {
    117 /*错误出现在这里,上面我是只搜索了左边,并且只计算了7个y值比c[i].y大的点到c[i]的距离,
    118 可是实际上y值比c[i].y小的点也有可能与c[i]取得最小值,所以说上面的程序有错误。真正正确
    119 的解答如下,那就是要搜索所有的点,并计算7个y值比c[i].y大的点到c[i]的距离,由于距离是两个
    120 点之间产生的,一个点的y值比另一个点小,那么必然有另一个点的y值比一个点的大,由于这种关系,
    121 从而保证了搜索出来的是最小的距离!
    122 */
    123             for (j = 1; (j <= 7) && (i + j < p); j++)
    124             {
    125                 if (c[i].index != c[i + j].index) /*最小值只可能出现在两个分别属于不同的边的点上*/
    126                 {
    127                     min = getDistance(c[i], c[i + j]);
    128                     if(min < dis)
    129                     dis = min;
    130                 }
    131             }
    132         }
    133     }
    134     return dis;
    135 }
    136 
    137 
    138 int main ()
    139 {
    140     int n;
    141     while (cin >> n && n != 0)
    142     {
    143         double result = 0;
    144 
    145         for (int i = 0; i < n; i++)
    146         {
    147             num[i].index = 0;
    148             cin >> num[i].x >> num[i].y;
    149         }
    150 
    151         sort (num, num + n, cmpx);
    152 
    153         result = divide_conquer(0, n - 1);
    154 
    155         printf("%.2lf
    ", result / 2);
    156     }
    157     //system ("pause");
    158     return 0;
    159 }
    View Code

    另一位大神的代码:

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<math.h>
    using namespace std;
    #define N 100005
    struct TPoint
    {
    double x,y;
    }ply[N],ans[N];
    int n;
    double MIN(double a,double b) {return a<b?a:b;}
    bool cmpx(TPoint a,TPoint b) {return a.x<b.x;}
    bool cmpy(TPoint a,TPoint b) {return a.y<b.y;}
    double dist(TPoint a,TPoint b)
    {
    double s1=a.x-b.x;
    double t1=a.y-b.y;
    return sqrt(s1*s1+t1*t1);
    }
    double closest(int l,int r)
    {
    if(l+1==r) return dist(ply[l],ply[r]);//2点
    else if(l+2==r)//三点
    return MIN(dist(ply[l],ply[l+1]),MIN(dist(ply[l],ply[r]),dist(ply[l+1],ply[r])));
    int i,j,mid,cnt;
    mid=(l+r)>>1;
    double min=MIN(closest(l,mid),closest(mid+1,r));//递归解决
    for(i=l,cnt=0;i<=r;i++)//相邻点符合
    {
    if(fabs(ply[i].x-ply[mid].x)<=min)
    ans[cnt++]=ply[i];
    }
    sort(ans,ans+cnt,cmpy);//按y排序
    for(i=0;i<cnt;i++) for(j=i+1;j<cnt;j++)//更新最小距离
    {
    if(ans[j].y-ans[i].y>=min) break;
    min=MIN(min,dist(ans[i],ans[j]));
    }
    return min;
    }
    int main()
    {
    while(scanf("%d",&n),n)
    {
    int i;
    for(i=0;i<n;i++) scanf("%lf%lf",&ply[i].x,&ply[i].y);//输入点
    sort(ply,ply+n,cmpx);//按x排序
    double min=closest(0,n-1);
    printf("%.2lf ",min/2);
    }
    return 0;
    }

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define N 100005
    using namespace std;
    
    struct Point
    {
    	double x,y;
    }ply[N],ans[N];
    
    int n;
    
    
    double MIN(double a, double b){return a<b?a:b;}
    
    bool cmpx(Point a, Point b){return a.x<b.x;}
    
    bool cmpy(Point a, Point b){return a.y<b.y;}
    
    
    double dist(Point a, Point b)
    {
        double s1=a.x-b.x;
    	double s2=a.y-b.y;
    
    	return sqrt(s1*s1+s2*s2);
    }
    
    double closet(int l,int r)
    {
        if(l+1==r)return dist(ply[l], ply[r]);//2点
    	else if(l+2==r)//3点
    		return MIN(dist(ply[l], ply[l+1]),MIN(dist(ply[l+1], ply[r]), dist(ply[l], ply[r])));
    
    	int i,j,mid,cnt;
    
    	mid=(l+r)>>1;//取中位数
    
    	double min=MIN(closet(l, mid), closet(mid+1, r));//递归解决
    
    	for(i=l,cnt=0;i<=r;i++)//相邻点符合
    	{
    	    if(fabs(ply[i].x-ply[mid].x)<=min)
    			ans[cnt++]=ply[i];
    	}
    
    	sort(ans, ans+cnt, cmpy);//按y排序
    
    	for(i=0;i<cnt;i++)
    		for(j=i+1;j<cnt;j++)//更新最小距离
    		{
    			if(ans[j].y-ans[i].y>=min)break;
    			min=MIN(min, dist(ans[i], ans[j]));
    		}
    
    	return min;
    }
    
    
    int main()
    {
    	while(cin>>n,n)
    	{
    		int i;
    		for(i=0;i<n;i++)cin>>ply[i].x>>ply[i].y;
    
    		sort(ply, ply+n, cmpx);
    
    		double min=closet(0, n-1);
    
    		printf("%.2lf
    ",min/2);
    	}
    
    	//system("pause");
    	return 0;
    }
    

      

    世上无难事,只要肯登攀。
  • 相关阅读:
    多样三角形
    字符串转化去重
    捕获异常里面的特殊异常
    sqlalchemy.exc.CompileError: (in table 'language_label', column 'name'): VARCHAR requires a length o
    机器学习总结
    找出两个列表中相同元素与不同元素
    正则去重
    mysql5.7 安装重置密码
    chrome快捷键
    golang select
  • 原文地址:https://www.cnblogs.com/littlehoom/p/3426103.html
Copyright © 2011-2022 走看看