POJ3608(旋转卡壳求两个多边形最短距离)

不是特别会搞这个问题,大致思想跟凸包内部求最远点对类似。先抄一发留作模板233

#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<iostream>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<iomanip>
using namespace std;

const double pi=acos(-1.0);
#define ll long long
#define pb push_back

#define sqr(a) ((a)*(a))
#define dis(a,b) sqrt(sqr(a.x-b.x)+sqr(a.y-b.y))

const double eps=1e-10;
const int maxn=5e4+56;
const int inf=0x3f3f3f3f;

struct Point{
    double x,y;
    Point(){}
    Point(double x,double y):x(x),y(y){}
    Point operator -(const Point &p){return Point(x-p.x,y-p.y);}
    bool operator<(const Point &a)const{
         if(x!=a.x)return x<a.x;
         else return y<a.y;
    }
    double dot(const Point&p){return x*p.x+y*p.y;}
    double det(const Point&p){return x*p.y-y*p.x;}
};
Point P[maxn],Q[maxn];

//AB与AC的叉积,正表示C在向量AB的逆时针方向
double cross(Point A,Point B,Point C){
    return (B-A).det(C-A);
}
//AB与AC的点积,0则垂直
double multi(Point A,Point B,Point C){
    return (B-A).dot(C-A);
}

void anticlockwise_sort(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 point_to_line(Point A,Point B,Point C){
    if(dis(A,B)<eps)return dis(B,C);
    if(multi(A,B,C)<-eps)return dis(A,C);
    if(multi(B,A,C)<-eps)return dis(B,C);
    return fabs(cross(A,B,C)/dis(A,B)); //面积
}
//两线段AB到CD的距离
double line_to_line(Point A,Point B,Point C,Point D){
    return min(min(point_to_line(A,B,C),point_to_line(A,B,D)),//四种可能
                min(point_to_line(C,D,A),point_to_line(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 arg,ans=inf;
    for(int i=0;i<n;i++){   //枚举p上的点
        while(arg=(cross(P[yminP+1],Q[ymaxQ+1],P[yminP]) - cross(P[yminP+1],Q[ymaxQ],P[yminP]))>eps){
            ymaxQ=(ymaxQ+1)%m;
        }
        ans=min(ans,line_to_line(P[yminP],P[yminP+1],Q[ymaxQ],Q[ymaxQ+1]));
        yminP=(yminP+1)%n;
    }
    return ans;
}

int main(){
    int N,M;
    while(~scanf("%d%d",&N,&M)&&N){
        for(int i=0;i<N;i++){
            scanf("%lf%lf",&P[i].x,&P[i].y);
        }
        for(int i=0;i<M;i++){
            scanf("%lf%lf",&Q[i].x,&Q[i].y);
        }
        anticlockwise_sort(P,N);anticlockwise_sort(Q,M);
        printf("%.5lf\n",solve(P,Q,N,M));
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/humveea6/article/details/80258601