分治——最小点对(HDU 1007)

本文解决HDU 1007问题,采用分治策略求解二维平面上N个点之间的最小距离。文章分享了一段AC代码,并特别提到了在使用宏定义时的一个常见陷阱。
  • 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1007

  • 题意:给出一个二维平面和N个点,求两点间的最小距离

  • 分析:分治即可

  • P.S.:发现一个大坑!!!!!#define MIN(x,y) x < y?x:y 只能传变量,不能传函数和其他表达式!!!否则比较的时候计算一次,出来又计算一次,绝壁超时啊 !!!!! 在这TLE了3个小时刷了2页submition啊啊啊!

  • AC代码


/*************************************************************************
    > File Name: 1007.cpp
    > Author: Akira
    > Mail: qaq.febr2.qaq@gmail.com
    > Created Time: 2017年01月17日 星期二 10时44分03秒
 ************************************************************************/

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<cmath>
#include<vector>
#include<set>
#include<list>
#include<ctime>
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define Sqr(a) ((a)*(a))

using namespace std;

#define MaxN 100001
#define MaxM MaxN*10
#define INF 0x3f3f3f3f
#define EPS 1e-8
#define bug cout << 88888888 << endl;
#define MIN(x,y) (x<y?x:y)
#define MAX(x,y) (x>y?x:y)

int N;
struct Point{double x,y;}point[MaxN];
bool cmp (Point a, Point b)
{
    if(a.x == b.x) return a.y<b.y;
    return a.x<b.x;
}

bool cmpQ(Point a, Point b)
{
    if(a.y==b.y) return a.x<b.x;
    return a.y>b.y;
}

double dis(Point a, Point b)
{
    return sqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) );
}

double check(double d, int mid,int l ,int r)
{
    vector<Point> V;
    double midx = point[mid].x;

    for(int i=l;i<=r;i++)
    {
        if( fabs(point[i].x - midx) <d  ) V.push_back(point[i]);
    }

    mid = V.size()/2;
    vector<Point> CV;
    for(int i=0;i<V.size();i++)
    {
        if(fabs(V[i].y - V[mid].y) <d) CV.push_back(V[i]);
    }
    sort(CV.begin(), CV.end(), cmpQ);
    double ans = d;
    for(int i=0;i<CV.size();i++)
    {
        for(int j=i+1;j<CV.size()&&j<=i+5;j++)
        {
            ans = min(ans, dis(CV[i], CV[j]));
        }
    }
    return ans;
}

double solve(int l, int r)
{
    if(r-l>2)
    {
        int mid = (r+l)/2;
        double ans = min(solve(l,mid), solve(mid+1,r));
        ans = check(ans, mid,l,r);
        return ans;
    }
    else
    {
        double ans = INF*1.0;
        for(int i=l;i<=r;i++)
        {
            for(int j=i+1;j<=r;j++)
            {
                ans = MIN(ans, dis(point[i],point[j]));
            }
        }
        return ans;

    }
}


int main()
{
    int N;
    while(~scanf("%d", &N) && N)
    {
        for(int i=1;i<=N;i++)
        {
            scanf("%lf%lf", &point[i].x, &point[i].y);
        }
        sort(point+1, point+1+N, cmp);
        double ans = solve(1,N);
        printf("%.2lf\n", ans/2.0);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值