现在的位置: 首页 > 综合 > 正文

POJ3608

2014年03月06日 ⁄ 综合 ⁄ 共 2190字 ⁄ 字号 评论关闭

计算两个凸包之间的最小距离,旋转卡壳法详解在旋转卡壳的用法之计算两个凸 包上的最近距离

#include <iostream>
#include<cstdio>
#include<string.h>
#include<cmath>
using namespace std;
const double eps=1e-10;
const double INF=1e10;
struct point
{
    double x,y;
    point (double a=0,double b=0)
    {
        x=a;
        y=b;
    }
};
double min_val(double a,double b)
{
    return a>b?b:a;
}
int dcmp(double a)
{
    if(fabs(a)<eps)return 0;
    else return a>0?1:-1;
}
point operator -(point a,point b){ return point (a.x-b.x,a.y-b.y); }
bool operator ==(const point &a,const point &b)
{
    return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
}
double cross(point a,point b)
{
    return a.x*b.y-a.y*b.x;
}
void readdate(point a[],int n,point b[],int m)
{
    int i;
    for(i=0;i<n;i++)
    scanf("%lf%lf",&a[i].x,&a[i].y);
    for(i=0;i<m;i++)
    scanf("%lf%lf",&b[i].x,&b[i].y);
}
void change(point a[],int b)
{
    int i;
    point temp;
    for(i=0;i<b/2;i++)
    {
        temp=a[i];
        a[i]=a[b-1-i];
        a[b-1-i]=temp;
    }
}
void work(point p[],int n,point q[],int m)
{
    int i;
    for(i=0;i<n-2;i++)
    if(dcmp(cross(p[i+1]-p[i],p[i+2]-p[i])>0)) break;
    else if(dcmp(cross(p[i+1]-p[i],p[i+2]-p[i])<0))
    {
        change(p,n);
        break;
    }
    for(i=0;i<m-2;i++)
    if(dcmp(cross(q[i+1]-q[i],q[i+2]-q[i])>0))break;
    else if(dcmp(cross(q[i+1]-q[i],q[i+2]-q[i])<0))
    {
        change(q,m);
        break;
    }
}
double Dot(point A,point B){return A.x*B.x+A.y*B.y;}
double Length(point A){return sqrt(Dot(A,A));}
double dist(point a,point b,point p)
{
    if(a==b) return Length(p-a);
    point v1=b-a,v2=p-a,v3=p-b;
    if(dcmp(Dot(v1,v2))<0)return Length(v2);
    if(dcmp(Dot(v1,v3))>0)return Length(v3);
    return fabs(cross(v1,v2))/Length(v1);

}
double Mid(point a1,point a2,point b1,point b2)
{
    return min_val(min_val(dist(a1,a2,b1),dist(a1,a2,b2)),
                   min_val(dist(b1,b2,a1),dist(b1,b2,a2)));
}
double solve(point P[],int n,point Q[],int m)
{
    double ans=INF,temp;
    int i,minP=0,maxQ=0;
    for(i=0;i<n;i++)
    if(P[i].y<P[minP].y)
    minP=i;
    for(i=0;i<m;i++)
    if(Q[i].y>Q[maxQ].y)
    maxQ=i;
    Q[m]=Q[0];
    P[n]=P[0];
    for(i=0;i<n;i++)
    {
        while((temp=cross(Q[maxQ+1]-P[minP+1],P[minP]-P[minP+1])
               -cross(Q[maxQ]-P[minP+1],P[minP]-P[minP+1]))>eps)
        maxQ=(maxQ+1)%m;
        if(temp<-eps)
            ans=min_val(ans,dist(P[minP],P[minP+1],Q[maxQ]));
        else ans=min_val(ans,Mid(P[minP],P[minP+1],Q[maxQ],Q[maxQ+1]));
        minP=(minP+1)%n;
    }
    return ans;
}
int main()
{
    point p[10005],q[10005];
    int n,m;
    double a,b;
    while(scanf("%d%d",&n,&m)==2)
    {
        if(m==0&&n==0)break;
        readdate(p,n,q,m);
        work(p,n,q,m);
       a=solve(p,n,q,m);
       b=solve(q,m,p,n);
       printf("%.5lf\n",min_val(a,b));
    }
    return 0;
}

抱歉!评论已关闭.