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

\(\color{#0066ff}{题目描述}\)

几千年前,有一个小王国位于太平洋的中部。王国的领土由两个分离的岛屿组成。由于洋流的冲击,两个岛屿的形状都变成了凸多边形。王国的国王想建立一座桥来连接这两个岛屿。为了把成本降到最低,国王要求你,主教,找到两个岛屿边界之间最小的距离。

\(\color{#0066ff}{输入格式}\)

输入由几个测试用例组成。
每个测试用两个整数n,m(3≤n,m≤10000)开始
接下来的n行中的每一行都包含一对坐标,用来描述顶点在一个凸多边形中的位置。
下一条m线中的每一条都包含一对坐标,它描述了一个顶点在另一个凸多边形中的位置。
n=m=0的行表示输入的结束。
坐标在这个范围内[-10000,10000]。

\(\color{#0066ff}{输出格式}\)

对每个测试用例输出最小距离。在0.001范围内的错误是可以接受的

\(\color{#0066ff}{输入样例}\)

4 4
0.00000 0.00000
0.00000 1.00000
1.00000 1.00000
1.00000 0.00000
2.00000 0.00000
2.00000 1.00000
3.00000 1.00000
3.00000 0.00000
0 0

\(\color{#0066ff}{输出样例}\)

1.00000

\(\color{#0066ff}{数据范围与提示}\)

none

\(\color{#0066ff}{题解}\)

旋转卡壳

输入的时候就是凸包,所以不用再求了

对于最近距离,可能是点点,点边, 边边,这个可以在点到边的距离那里一并处理

距离可以通过面积判断(底固定,高最大)

(叉积是负的,所以用<) 找到高最小的更新ans

#include <cstdio>
#include <cmath>
#include <cctype>
#include <algorithm>
#define _ 0
#define LL long long
inline LL in() {
    LL x = 0, f = 1; char ch;
    while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    while(isdigit(ch)) x = x * 10 + (ch ^ 48), ch = getchar();
    return x * f;
}
const int maxn = 1e4 + 100;
int n, m;
struct node {
    double x, y;
    node(double x = 0, double y = 0)
        :x(x), y(y) {}
    node operator - (const node &b) const {
        return node(x - b.x, y - b.y);
    }
    double operator ^ (const node &b) const {
        return x * b.y - y * b.x;
    }
    double operator * (const node &b) const {
        return x * b.x + y * b.y;
    }
    double dis() {
        return sqrt(x * x + y * y);
    }
    double dis(const node &a, const node &b) {
        node c = *this;
        //垂足不在线段ab上
        if((b - a) * (c - a) < 0) return (c - a).dis();
        if((a - b) * (c - b) < 0) return (c - b).dis();
        //平行四边形面积 / 底 = 高
        return fabs(((a - b) ^ (c - b)) / (a - b).dis());
    }
}A[maxn], B[maxn];
double Min(node a, node b, node c, node d) {
    return std::min(std::min(c.dis(a,b),d.dis(a,b)),std::min(a.dis(c,d),b.dis(c,d)));
}
double work() {
    double ans = 1e20;
    int min = 0, max = 0;
    for(int i = 0; i < n; i++) if(A[i].y < A[min].y) min = i;
    for(int i = 0; i < m; i++) if(B[i].y > B[max].y) max = i;
    A[n] = A[0], B[m] = B[0];
    for(int i = 0; i < n; i++) {
        node t = A[min + 1] - A[min];
        while((t ^ (B[max] - A[min]))  < (t ^ (B[max + 1] - A[min]))) max = (max + 1) % m;
        ans = std::min(ans, Min(A[min], A[min + 1], B[max], B[max + 1]));
        min = (min + 1) % n;
    }
    return ans;
}
int main() {
    while("fuck") {
        n = in(), m = in();
        if(!n && !m) break;
        for(int i = 0; i < n; i++) scanf("%lf%lf", &A[i].x, &A[i].y);
        for(int i = 0; i < m; i++) scanf("%lf%lf", &B[i].x, &B[i].y);
        printf("%.3f\n", work());
    }
    return 0;
}

原文地址:https://www.cnblogs.com/olinr/p/10193805.html

时间: 2024-08-12 04:36:58

Bridge Across Islands POJ - 3608 旋转卡壳求凸包最近距离的相关文章

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坐标,不用科学计

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

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

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

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个不同的点,要求在这些点里寻找三个点,使他们构成的三角

POJ 2187 旋转卡壳 + 水平序 Graham 扫描算法

水平序 Graham 扫描算法: 计算二维凸包的时候可以用到,Graham 扫描算法有水平序和极角序两种. 极角序算法能一次确定整个凸包, 但是计算极角需要用到三角函数,速度较慢,精度较差,特殊情况较多. 水平序算法需要扫描两次,但排序简单,讨论简单,不易出错. [算法流程] 1.对顶点按x为第一关键字,y为第二关键字进行排序. 2.准备一个空栈,并将前两个点压入栈. 3.对于每一个顶点A,只要栈顶中还至少两个顶点,记栈顶为T,栈中第二个为U. 若UT(向量) * TA(向量) <= 0, 则将

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 #

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