【轉載】-HDU 1007 hdu 1007 Quoit Design (最近點對)

Quoit Design
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 34731 Accepted Submission(s): 9062

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

轉自:http://www.cnblogs.com/ACMDoli/articles/4292029.html
轉自:http://blog.csdn.net/hellobabygogo3/article/details/8042650

先說下題意,很簡單,給n個點的座標,求距離最近的一對點之間距離的一半。第一行是一個數n表示有n個點,接下來n行是n個點的x座標和y座標,實數。

這個題目其實就是求最近點對的距離。主要思想就是分治。先把n個點按x座標排序,然後求左邊n/2個和右邊n/2個的最近距離,最後合併。合併要重點說一下,比較麻煩。

首先,假設點是n個,編號爲1到n。我們要分治求,則找一箇中間的編號mid,先求出1到mid點的最近距離設爲d1,還有mid+1到n的最近距離設爲d2。這裏的點需要按x座標的

順序排好,並且假設這些點中,沒有2點在同一個位置。(若有,則直接最小距離爲0了)。

 然後,令d爲d1, d2中較小的那個點。如果說最近點對中的兩點都在1-mid集合中,或者mid+1到n集合中,則d就是最小距離了。但是還有可能的是最近點對中的兩點分屬

這兩個集合,所以我們必須先檢測一下這種情況是否會存在,若存在,則把這個最近點對的距離記錄下來,去更新d。這樣我們就可以得道最小的距離d了。

 關鍵是要去檢測最近點對,理論上每個點都要和對面集合的點匹配一次,那效率還是不能滿足我們的要求。所以這裏要優化。怎麼優化呢?考慮一下,假如以我們所選的

分割點mid爲界,如果某一點的橫座標到點mid的橫座標的絕對值超過d1並且超過d2,那麼這個點到mid點的距離必然超過d1和d2中的小者,所以這個點到對方集合的任意點的

距離必然不是所有點中最小的。

 所以我們先把在mid爲界左右一個範圍內的點全部篩選出來,放到一個集合裏。篩選好以後,當然可以把這些點兩兩求距離去更新d了,不過這樣還是很慢,萬一滿足條件的

點很多呢。這裏還得繼續優化。首先把這些點按y座標排序。假設排序好以後有cnt個點,編號爲0到cnt-1。那麼我們用0號去和1到cnt-1號的點求一下距離,然後1號和2到cnt-1

號的點求一下距離。。。如果某兩個點y軸距離已經超過了d,這次循環就可以直接break了,開始從下一個點查找了.

代碼:

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
using namespace std;
const double eps = 1e-6;
const int MAXN = 100010;
const double INF = 1e20;
struct Point
{
    double x,y;
};
double dist(Point a,Point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}
Point p[MAXN];
Point tmpt[MAXN];
bool cmpxy(Point a,Point b)
{
    if(a.x != b.x)return a.x < b.x;
    else return a.y < b.y;
}
bool cmpy(Point a,Point b)
{
    return a.y < b.y;
}
double Closest_Pair(int left,int right)
{
    double d = INF;
    if(left == right)return d;
    if(left + 1 == right)
        return dist(p[left],p[right]);
    int mid = (left+right)/2;
    double d1 = Closest_Pair(left,mid);
    double d2 = Closest_Pair(mid+1,right);
    d = min(d1,d2);
    int k = 0;
    for(int i = left; i <= right; i++)
    {
        if(fabs(p[mid].x - p[i].x) <= d)
            tmpt[k++] = p[i];
    }
    sort(tmpt,tmpt+k,cmpy);
    for(int i = 0; i <k; i++)
    {
        for(int j = i+1; j < k && tmpt[j].y - tmpt[i].y < d; j++)
        {
            d = min(d,dist(tmpt[i],tmpt[j]));
        }
    }
    return d;
}
int main()
{
    int n;
    while(scanf("%d",&n)==1 && n)
    {
        for(int i = 0; i < n; i++)
            scanf("%lf%lf",&p[i].x,&p[i].y);
        sort(p,p+n,cmpxy);
        printf("%.2lf\n",Closest_Pair(0,n-1)/2);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章