POJ3608(旋转卡壳--求两凸包的最近点对距离)

分析:以下内容来自:http://blog.csdn.net/acmaker/article/details/3178696

考虑如下的算法, 算法的输入是两个分别有m和n个顺时针给定顶点的凸多边形P和Q。

1.计算P上y坐标值最小的顶点(称为 yminP )和Q上y坐标值最大的顶点(称为 ymaxQ)。

2.为多边形在 yminP 和 ymaxQ 处构造两条切线 LP 和 LQ 使得他们对应的多边形位于他们的右侧。

  此时 LP 和 LQ 拥有不同的方向, 并且 yminP 和 ymaxQ 成为了多边形间的一个对踵点对。

3.计算距离(yminP,ymaxQ) 并且将其维护为当前最小值。

4.顺时针同时旋转平行线直到其中一个与其所在的多边形的边重合。

5.如果只有一条线与边重合, 那么只需要计算“顶点-边”对踵点对和“顶点-顶点”对踵点对距离。 都将他们与当前最小值

比较, 如果小于当前最小值则进行替换更新。如果两条切线都与边重合,那么情况就更加复杂了。如果边“交叠”,也就是

可以构造一条与两条边都相交的公垂线(但不是在顶点处相交), 那么就计算“边-边”距离。 否则计算三个新的“顶点-顶

点”对踵点对距离。 所有的这些距离都与当前最小值进行比较, 若小于当前最小值则更新替换。

6.重复执行步骤4和步骤5, 直到新的点对为(yminP,ymaxQ)。

7.输出最小距离。

#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <math.h>

using namespace std;

const int N=50000;
const double eps=1e-9;
const double INF=1e99;

struct Point
{
    double x,y;
};

Point P[N],Q[N];

double cross(Point A,Point B,Point C)
{
    return (B.x-A.x)*(C.y-A.y)-(B.y-A.y)*(C.x-A.x);
}

double dist(Point A,Point B)
{
    return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

double multi(Point A,Point B,Point C)
{
    return (B.x-A.x)*(C.x-A.x)+(B.y-A.y)*(C.y-A.y);
}

//顺时针排序
void anticlockwise(Point p[],int n)
{
    for(int i=0;i<n-2;i++)
    {
        double tmp=cross(p[i],p[i+1],p[i+2]);
        if(tmp>eps) return;
        else if(tmp<-eps)
        {
            reverse(p,p+n);
            return;
        }
    }
}

//计算C点到直线AB的最短距离
double Getdist(Point A,Point B,Point C)
{
    if(dist(A,B)<eps) return dist(B,C);
    if(multi(A,B,C)<-eps) return dist(A,C);
    if(multi(B,A,C)<-eps) return dist(B,C);
    return fabs(cross(A,B,C)/dist(A,B));
}

//求一条直线的两端点到另外一条直线的距离,反过来一样,共4种情况
double MinDist(Point A,Point B,Point C,Point D)
{
    return min(min(Getdist(A,B,C),Getdist(A,B,D)),min(Getdist(C,D,A),Getdist(C,D,B)));
}

double Solve(Point P[],Point Q[],int n,int m)
{
    int yminP=0,ymaxQ=0;
    for(int i=0;i<n;i++)
       if(P[i].y<P[yminP].y)
          yminP=i;
    for(int i=0;i<m;i++)
       if(Q[i].y>Q[ymaxQ].y)
          ymaxQ=i;
    P[n]=P[0];
    Q[m]=Q[0];
    double tmp,ans=INF;
    for(int i=0;i<n;i++)
    {
        while(tmp=cross(P[yminP+1],Q[ymaxQ+1],P[yminP])-cross(P[yminP+1],Q[ymaxQ],P[yminP])>eps)
            ymaxQ=(ymaxQ+1)%m;
        if(tmp<-eps) ans=min(ans,Getdist(P[yminP],P[yminP+1],Q[ymaxQ]));
        else         ans=min(ans,MinDist(P[yminP],P[yminP+1],Q[ymaxQ],Q[ymaxQ+1]));
        yminP=(yminP+1)%n;
    }
    return ans;
}

int main()
{
    int n,m;
    while(cin>>n>>m)
    {
        if(n==0&&m==0) break;
        for(int i=0;i<n;i++)
           cin>>P[i].x>>P[i].y;
        for(int i=0;i<m;i++)
           cin>>Q[i].x>>Q[i].y;
        anticlockwise(P,n);
        anticlockwise(Q,m);
        printf("%.5lf\n",min(Solve(P,Q,n,m),Solve(Q,P,m,n)));
    }
    return 0;
}

时间: 2024-10-18 15:47:25

POJ3608(旋转卡壳--求两凸包的最近点对距离)的相关文章

poj 3608(旋转卡壳求解两凸包之间的最短距离)

Bridge Across Islands Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9768   Accepted: 2866   Special Judge Description Thousands of thousands years ago there was a small kingdom located in the middle of the Pacific Ocean. The territory

HDOJ 2202 最大三角形 凸包旋转卡壳求最大三角形面积

凸包旋转卡壳求最大三角形面积 最大三角形 Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3316    Accepted Submission(s): 1119 Problem Description 老师在计算几何这门课上给Eddy布置了一道题目,题目是这样的:给定二维的平面上n个不同的点,要求在这些点里寻找三个点,使他们构成的三角

hdu 3934&amp;&amp;poj 2079 (凸包+旋转卡壳+求最大三角形面积)

链接:http://poj.org/problem?id=2079 Triangle Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 8173   Accepted: 2423 Description Given n distinct points on a plane, your task is to find the triangle that have the maximum area, whose vertices

poj 2079 Triangle,旋转卡壳求点集的最大三角形

给出一个点集,求顶点在点集中的最大的三角形面积. 我们知道这三角形的三个点肯定在凸包上,我们求出凸包之后不能枚举,因为题目n比较大,枚举的话要O(n^3)的数量级,所以采用旋转卡壳的做法: 首先枚举三角形的第一个顶点i, 初始化第二个顶点j=i+1和第三个顶点k=j+1,对k进行循环,直到找到第一个k使得cross(i,j,k)>cross(i,j,k+1),如果k==i进入下一次循环. 对j,k进行旋转,每次循环之前更新最大值,然后固定一个j,同样找到一个k使得cross(i,j,k)>cr

bzoj1185 [HNOI2007]最小矩形覆盖 旋转卡壳求凸包

[HNOI2007]最小矩形覆盖 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 2081  Solved: 920[Submit][Status][Discuss] Description 给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形, 输出所求矩形的面积和四个顶点坐标 Input 第一行为一个整数n(3<=n<=50000) 从第2至第n+1行每行有两个浮点数,表示一个顶点的x和y坐标,不用科学计

Bridge Across Islands POJ - 3608 旋转卡壳求凸包最近距离

\(\color{#0066ff}{题目描述}\) 几千年前,有一个小王国位于太平洋的中部.王国的领土由两个分离的岛屿组成.由于洋流的冲击,两个岛屿的形状都变成了凸多边形.王国的国王想建立一座桥来连接这两个岛屿.为了把成本降到最低,国王要求你,主教,找到两个岛屿边界之间最小的距离. \(\color{#0066ff}{输入格式}\) 输入由几个测试用例组成. 每个测试用两个整数n,m(3≤n,m≤10000)开始 接下来的n行中的每一行都包含一对坐标,用来描述顶点在一个凸多边形中的位置. 下一条

bzoj1069: [SCOI2007]最大土地面积 凸包+旋转卡壳求最大四边形面积

在某块平面土地上有N个点,你可以选择其中的任意四个点,将这片土地围起来,当然,你希望这四个点围成的多边形面积最大. 题解:先求出凸包,O(n)枚举旋转卡壳,O(n)枚举另一个点,求最大四边形面积 /************************************************************** Problem: 1069 User: walfy Language: C++ Result: Accepted Time:892 ms Memory:1360 kb ****

【模板】旋转卡壳求 面积最大的三角形 poj2079

题目链接:https://vjudge.net/problem/POJ-2079 graham跑的巨慢,Andrew跑的巨快.还好写. 有两种写法. 旋转卡壳枚举三个点的(94ms) 1 /************************************************************************* 2 > File Name: poj2079.cpp 3 # File Name: poj2079.cpp 4 # Author : xiaobuxie 5 #

UVA 4728 Squares(凸包+旋转卡壳)

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=17267 [思路] 凸包+旋转卡壳 求出凸包,用旋转卡壳算出凸包的直径即可. [代码] 1 #include<cstdio> 2 #include<vector> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 struct Pt { 8