POJ 3608 求两个凸包之间的最小距离

来源:互联网 发布:网络辣条是什么意思 编辑:程序博客网 时间:2024/06/01 21:48

题解 :

首先我们要知道一种遍历所有对踵点的算法 : 就是用旋转卡壳加上叉积判断是否旋转的一种算法。
剩下的就是求对踵点了
因为我们不难发现,对于两个凸包来说,他们之间的最小距离肯定在对踵点上。然后我们就可以去便利所有的对踵点这样同时保留最小距离这样就可以了。注意求一个线段到另一条线段的最小距离应该用点积去算就好了
还有我们需要深入理解关于旋转卡壳的几个有关的概念
1. 支撑线
2. 对踵点
3. 什么时候卡壳旋转
4. 旋转卡壳

只有这些理解到位以后才可以做这道题 注意对于多个凸包而言,我们需要每一个都去做一遍旋转卡壳。\

#include <iostream>#include <cstring>#include <cmath>#include <algorithm>#include <cstdio>using namespace std;const int maxn = 1e4 + 10;const double eps = 1e-8;const double INF = 1e88;struct node {    double x,y;}p[maxn],q[maxn];node init;int sgn (double x) {    if (fabs (x) < eps) return 0;    return x > 0 ? 1 : -1;}double cross (double x1,double y1,double x2,double y2) {    return x1 * y2 - x2 * y1;}double muit (double x1,double y1,double x2,double y2) {    return x1 * x2 + y1 * y2;}double dist (node a,node b) {    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));}bool cmp (const node a,const node b) {    int sg = sgn (cross (a.x - init.x,a.y - init.y,b.x - init.x,b.y - init.y));    if (sg == 0) return dist (a,init) < dist (b,init);    return sg > 0;}double dist (node a,node b,node c) {    if (dist (a,b) < eps) return dist (a,c);    if (sgn(muit(b.x - a.x, b.y - a.y, c.x - a.x, c.y - a.y)) < 0) return dist (a,c);    if (sgn(muit(a.x - b.x, a.y - b.y, c.x - b.x, c.y - b.y) < 0)) return dist (b,c);    return fabs (cross(c.x - a.x, c.y - a.y, b.x - a.x, b.y - a.y) / dist (a,b));}double ansdist (node a,node b,node c,node d) {    return min (min (dist (a,b,c),dist (a,b,d)),min(dist (c,d,a),dist (c,d,b)));}void mysort (node a[],int n) {    for (int i = 1;i <= n; ++ i) {        if (a[i].y < a[1].y || (a[i].y == a[1].y && a[i].x < a[1].x)) {            swap (a[1],a[i]);        }    }    init = a[1];//    printf ("%.3f  %.3f\n",init.x,init.y);    sort (a + 1,a + 1 + n,cmp);}double rotating (node p[],node q[],int n,int m) {    int miny = 1,maxy = 1;    double mx = 0;    p[n + 1] = p[1];    q[m + 1] = q[1];    for (int i = 1;i <= m; ++ i) {        if (q[i].y > mx) {            mx = q[i].y;            maxy = i;        }    }    double ans = dist (p[miny],q[maxy]);    for (int i = 1;i <= n; ++ i) {        while ((cross (q[maxy + 1].x - p[miny + 1].x,q[maxy + 1].y - p[miny + 1].y,p[miny].x - p[miny + 1].x,p[miny].y - p[miny + 1].y)-cross (q[maxy].x - p[miny + 1].x,q[maxy].y - p[miny + 1].y,p[miny].x - p[miny + 1].x,p[miny].y - p[miny + 1].y)) > eps) {            maxy = maxy % m + 1;        }        ans = min (ans,ansdist (p[miny],p[miny + 1],q[maxy],q[maxy + 1]));        miny = miny % n + 1;    }    return ans;}int main () {    int n,m;    while (scanf ("%d%d",&n,&m) && n) {        for (int i = 1;i <= n; ++ i) {            scanf ("%lf%lf",&p[i].x,&p[i].y);        }        for (int i = 1;i <= m; ++ i) {            scanf ("%lf%lf",&q[i].x,&q[i].y);        }        mysort(p, n);        mysort(q, m);//        for (int i = 1;i <= m; ++ i) {//            printf ("%.3f  %.3f\n",q[i].x,q[i].y);//        }        printf ("%.5f\n",min (rotating(p, q, n, m),rotating(q, p, m, n)));    }    return 0;}