天天看點

HDU1007 Quoit Design

題目位址:http://acm.hdu.edu.cn/showproblem.php?pid=1007

具體算法分析見:最接近點對問題

版本一:

#include <iostream>

#include<cmath>

#include <cstdio>

#include <cstdlib>

#include <cstring>

using namespace std;

const int N = 100005;

const double MAX = 10e100;

const double eps = 0.00001;

typedef struct TYPE

{

    double x, y;

    int index;

} Point;

Point a[N], b[N], c[N];

double closest(Point *, Point *, Point *, int, int);

double dis(Point, Point);

int cmp_x(const void *, const void*);

int cmp_y(const void *, const void*);

int merge(Point *, Point *, int, int, int);

inline double min(double, double);

int main()

    int n, i;

    double d;

    scanf("%d", &n);

    while (n)

    {

        for (i = 0; i < n; i++)

            scanf("%lf%lf", &(a[i].x), &(a[i].y));

        qsort(a, n, sizeof(a[0]), cmp_x);

            a[i].index = i;

        memcpy(b, a, n *sizeof(a[0]));

        qsort(b, n, sizeof(b[0]), cmp_y);

        d = closest(a, b, c, 0, n - 1);

        printf("%.2lf\n", d/2);

        scanf("%d", &n);

    }

    return 0;

}

double closest(Point a[], Point b[], Point c[], int p, int q)

    if (q - p == 1)

        return dis(a[p], a[q]);

    if (q - p == 2)

        double x1 = dis(a[p], a[q]);

        double x2 = dis(a[p + 1], a[q]);

        double x3 = dis(a[p], a[p + 1]);

        if (x1 < x2 && x1 < x3)

            return x1;

        else if (x2 < x3)

            return x2;

        else

            return x3;

    int m = (p + q) / 2;

    int i, j, k;

    double d1, d2;

    for (i = p, j = p, k = m + 1; i <= q; i++)

        if (b[i].index <= m)

            c[j++] = b[i];

    //數組c左半部儲存劃分後左部的點, 且對y是有序的.

    else

        c[k++] = b[i];

    d1 = closest(a, c, b, p, m);

    d2 = closest(a, c, b, m + 1, q);

    double dm = min(d1, d2);

    merge(b, c, p, m, q); //數組c左右部分分别是對y坐标有序的, 将其合并到b.

    for (i = p, k = p; i <= q; i++)

        if (fabs(b[i].x - b[m].x) < dm)

            c[k++] = b[i];

    //找出離劃分基準左右不超過dm的部分, 且仍然對y坐标有序.

    for (i = p; i < k; i++)

    for (j = i + 1; j < k && c[j].y - c[i].y < dm; j++)

        double temp = dis(c[i], c[j]);

        if (temp < dm)

            dm = temp;

    return dm;

double dis(Point p, Point q)

    double x1 = p.x - q.x, y1 = p.y - q.y;

    return sqrt(x1 *x1 + y1 * y1);

int merge(Point p[], Point q[], int s, int m, int t)

    for (i = s, j = m + 1, k = s; i <= m && j <= t;)

        if (q[i].y > q[j].y)

            p[k++] = q[j], j++;

            p[k++] = q[i], i++;

    while (i <= m)

        p[k++] = q[i++];

    while (j <= t)

        p[k++] = q[j++];

    memcpy(q + s, p + s, (t - s + 1) *sizeof(p[0]));

int cmp_x(const void *p, const void *q)

    double temp = ((Point*)p)->x - ((Point*)q)->x;

    if (temp > 0)

        return 1;

    else if (fabs(temp) < eps)

        return 0;

        return  - 1;

int cmp_y(const void *p, const void *q)

    double temp = ((Point*)p)->y - ((Point*)q)->y;

inline double min(double p, double q)

    return (p > q) ? (q): (p);

版本二:(使用STL,未能AC掉,還得繼續測試。。。)

#include <cmath>

#include <vector>

#include <algorithm>

#include <iomanip>

class point

public:

    point(double x1=0.0f,double y1=0.0f,int id=0):x(x1),y(y1),id(id)

    ~point()

    double getX()const

        return x;

    double getY()const

        return y;

    void setID(int t)

        id = t;

    double getID()const

        return id;

    double Distance(const point& rhs)

    {//計算與另外一個點之間的距離

        double dx = (x-rhs.x);

        double dy = (y-rhs.y);

        return sqrt(dx*dx+dy*dy);

    friend ostream& operator << (ostream& out,const point& rhs)

        out<<rhs.x<<" "<<rhs.y<<" id is:"<<rhs.id<<endl;

        return out;

    bool operator < (const point& rhs)

        return x<rhs.x;

    point& operator = (const point& rhs)

        x = rhs.x;

        y = rhs.y;

        id = rhs.id;

        return *this;

private:

    double x;

    double y;

    int id;//點的編号

};

bool cmp_onY(const point& p,const point& q)

    return p.getY()<q.getY();

double min(const double& a,const double &b)

    return a<b?a:b;

void printVector(vector<point>& v)

    vector<point>::iterator iter;

    for(iter = v.begin();iter!=v.end();++iter)

        cout<<*iter<<endl;

int merge(vector<point>& a,vector<point>& b,int begin,int mid,int end)

{//合并

    for (i = begin, j = mid + 1, k = begin; i <= mid && j <= end;)

        if (b[i].getY() > b[j].getY())

            a[k++] = b[j], j++;

            a[k++] = b[i], i++;

    while (i <= mid)

        a[k++] = b[i++];

    while (j <= end)

        a[k++] = b[j++];

    vector<point>::iterator iter = a.begin();

    copy(iter+begin,iter+(end-begin+1),b.begin());

    return 0; 

double Closest(vector<point>& a,vector<point>& b,vector<point>& c,int begin,int last)

    int len = last-begin;

    if(len==1)

    {//隻有兩個了

        return a[begin].Distance(a[last]);

    if(len==2)

    {//還有三個

        double t1 = a[begin].Distance(a[last]);

        double t2 = a[begin].Distance(a[begin+1]);

        double t3 = a[begin+1].Distance(a[last]);

        if(t1<t2 && t1<t3)

            return t1;

        else if(t2<t3)

            return t2;

            return t3;

    int mid = (begin+last)/2;//分割點

    int i,j,k;

    double d1,d2;

    for(i = begin,j = begin,k = mid+1;i<=last;++i)

        if(b[i].getID()<=mid)

    d1 = Closest(a,c,b,begin,mid);

    d2 = Closest(a,c,b,mid+1,last);

    double dm = min(d1,d2);

    merge(b,c,begin,mid,last);

    for(i=begin,k=begin;i<=last;++i)

        if(fabs(b[i].getX()-b[mid].getX()) < dm)

    for(i=begin;i<k;++i)

        for(j = i+1;j<k&&(c[j].getY()-c[i].getY()<dm);j++)

        {

            double temp = c[i].Distance(c[j]);

            if(temp<dm)

                dm = temp;

        }

    int nPoints,i;

    double x1,y1,result=0.0f;

    vector<point> v1,v2,v3;

    while(cin>>nPoints&&nPoints!=0)

        for(i=0;i<nPoints;++i)

            cin>>x1>>y1;

            point tmp(x1,y1);

            v1.push_back(tmp);

        v3 = v1;

        sort(v1.begin(),v1.end());

            v1[i].setID(i);

        v2 = v1;

        sort(v2.begin(),v2.end(),cmp_onY);

        result = Closest(v1,v2,v3,0,nPoints-1);

        cout<<setiosflags(ios::fixed)<<setprecision(2);

        cout<<result/2<<endl;

        v1.erase(v1.begin(),v1.end());  

        v2.erase(v2.begin(),v2.end()); 

        v3.erase(v3.begin(),v3.end()); 

本文轉自Phinecos(洞庭散人)部落格園部落格,原文連結:http://www.cnblogs.com/phinecos/archive/2007/12/26/1015609.html,如需轉載請自行聯系原作者

繼續閱讀