uva10245-The Closest Pair Problem(平面上的点分治)

解析:平面上的点分治,先递归得到左右子区间的最小值d,
再处理改区间,肯定不会考虑哪些距离已经大于d的点对,
对y坐标归并排序,然后从小到大开始枚举更新d,对于某个点,
x轴方向只用考虑[x-d,x+d](x是分的中轴线),y轴方向只用考虑
[y-d,y](y是这个点的y值),因为d值一直在变小,所以这个矩形包
含的点数很少。

代码

#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<cmath>
#include<algorithm>
using namespace std;
const double INF=1e9;
const int maxn=10005;
int N;
struct Po
{
    double x,y;
    Po(double x=0,double y=0):x(x),y(y){}
}po[maxn],B[maxn];
bool cmp(const Po& a,const Po& b)
{
    if(a.x!=b.x) return a.x<b.x;
    return a.y<b.y;
}
double dfs(int l,int r)
{
    if(l>=r) return INF;
    int mid=(l+r)/2;
    double x=po[mid].x;
    double d=min(dfs(l,mid),dfs(mid+1,r)); //先处理左右子区间
    int ls=l,rs=mid+1,k=l;
    while(ls<=mid&&rs<=r) //归并排序
    {
        if(po[ls].y<=po[rs].y) B[k++]=po[ls++];
        else B[k++]=po[rs++];
    }
    while(ls<=mid) B[k++]=po[ls++];
    while(rs<=r) B[k++]=po[rs++];
    for(int i=l;i<=r;i++) po[i]=B[i];
    int Size=0;
    for(int i=l;i<=r;i++)
    {
        if(fabs(po[i].x-x)>=d) continue; //不考虑
        for(int j=Size;j>=1;j--)
        {
            double a=po[i].x-B[j].x;
            double b=po[i].y-B[j].y;
            if(b>=d) break;
            d=min(d,sqrt(a*a+b*b));  //更新
        }
        B[++Size]=po[i];
    }
    return d;
}
int main()
{
    while(scanf("%d",&N)!=EOF&&N)
    {
        double x,y;
        for(int i=1;i<=N;i++)
        {
            scanf("%lf%lf",&x,&y);
            po[i]=Po(x,y);
        }
        sort(po+1,po+N+1,cmp);
        double ans=dfs(1,N);
        if(ans<10000) printf("%.4f\n",ans);
        else printf("INFINITY\n");
    }
    return 0;
}

时间: 2024-07-30 21:59:44

uva10245-The Closest Pair Problem(平面上的点分治)的相关文章

uva10245 - The Closest Pair Problem(暴力+剪枝)

题目:uva10245 - The Closest Pair Problem(暴力+剪枝) 题目大意:给出N个点,求这些点中最小的两点距离. 解题思路:把这些点中两两之间的距离都算出来,这样的复杂度是O(n^2),会超时,所以加了一个减枝. 先将所有的点按照x坐标排序.然后在计算的过程中,如果发现要计算的这两点的X坐标之差的绝对值已经大于等于当前的最小值,那么说明后面的点计算距离一定比这个最小值要大. 这题的正解貌似是分治法,可惜没看懂. 代码: #include <stdio.h> #inc

uva 10245 The Closest Pair Problem (暴力+剪枝)

uva 10245 The Closest Pair Problem 题目大意:给出n个点,求出距离最近的两点间的距离.若点与点间的距离都大于10000,输出INFINITY 解题思路:这题的正统做法是分治,偷懒方法是暴力加剪枝.先按x坐标排序,然后fabs(p[i] - p[j]) > ans的点就可以直接跳过了. #include<stdio.h> #include<string.h> #include<stdlib.h> #include<algori

UVA - 10245 The Closest Pair Problem

属于Divide-and-Conquer,算法课老师有讲到,就找个题目试试,思想就是不断的二分...考虑合并时的处理..不解释 //============================================================================ // Name : uva10245.cpp // Author : // Version : // Copyright : Your copyright notice // Description : Uva10

UVa 10245 The Closest Pair Problem (分治)

题意:给定 n 个点,求最近两个点的距离. 析:直接求肯定要超时的,利用分治法,先把点分成两大类,答案要么在左边,要么在右边,要么一个点在左边一个点在右边,然后在左边或右边的好求,那么对于一个在左边一个在右边的,我们可以先求全在左边或右边的最小值,假设是d,那么一个点在左边,一个点在右边,那么横坐标之差肯定小于d,才能替换d,同样的纵坐标也是,并且这样的点并不多,然后就可以先选出来,再枚举. 代码如下: #pragma comment(linker, "/STACK:1024000000,102

Problem A: 平面上的点——Point类 (III)

Description 在数学上,平面直角坐标系上的点用X轴和Y轴上的两个坐标值唯一确定.现在我们封装一个"Point类"来实现平面上的点的操作. 根据"append.cc",完成Point类的构造方法和show()方法,输出各Point对象的构造和析构次序.实现showPoint()函数. 接口描述: showPoint()函数按输出格式输出Point对象,调用Point::show()方法实现. Point::show()方法:按输出格式输出Point对象. I

Problem E: 平面上的点——Point类 (II)

Description 在数学上,平面直角坐标系上的点用X轴和Y轴上的两个坐标值唯一确定.现在我们封装一个"Point类"来实现平面上的点的操作. 根据"append.cc",完成Point类的构造方法和show()方法,输出各Point对象的构造和析构次序. 接口描述: Point::show()方法:按输出格式输出Point对象. Input 输入多行,每行为一组坐标"x,y",表示点的x坐标和y坐标,x和y的值都在double数据范围内.

Problem A: 平面上的点和线——Point类、Line类 (I)

Description 在数学上,平面直角坐标系上的点用X轴和Y轴上的两个坐标值唯一确定,两点确定一条线段.现在我们封装一个"Point类"和"Line类"来实现平面上的点的操作. 根据"append.cc",完成Point类和Line类的构造方法和show()方法. 接口描述: Point::show()方法:按格式输出Point对象. Line::show()方法:按格式输出Line对象. Input 输入的第一行为N,表示后面有N行测试样例

Problem D: 平面上的点——Point类 (I)

Description 在数学上,平面直角坐标系上的点用X轴和Y轴上的两个坐标值唯一确定.现在我们封装一个"Point类"来实现平面上的点的操作. 根据"append.cc",完成Point类的构造方法和show()方法. 接口描述: Point::show()方法:按输出格式输出Point对象. Input 输入多行,每行为一组坐标"x,y",表示点的x坐标和y坐标,x和y的值都在double数据范围内. Output 输出为多行,每行为一个点

Problem B: 平面上的点和线——Point类、Line类 (II)

Description 在数学上,平面直角坐标系上的点用X轴和Y轴上的两个坐标值唯一确定,两点确定一条线段.现在我们封装一个"Point类"和"Line类"来实现平面上的点的操作. 根据"append.cc",完成Point类和Line类的构造方法和show()方法,输出各Line对象的构造和析构次序. 接口描述: Point::show()方法:按格式输出Point对象. Line::show()方法:按格式输出Line对象. Input 输入