您的位置:首页 > 其它

poj3608_Bridge Across Islands_旋转卡壳&&点到线段的距离

2017-12-30 18:22 447 查看

题意

给出两个凸包,现要用一条线段连接这两个凸包,求这条线段的最小长度。

思路

从第一个凸包y值最小的那个点,和第二个凸包y值最大的那个点出发,旋转卡壳。

链接

http://poj.org/problem?id=3608

代码

#include<cstdio>
#include<algorithm>
#include<cmath>

using namespace std;

const double eps = 1e-8;
const int maxn = 10101;
const double inf = 1e11;

struct P{
double x, y;

P(){}
P(double x, double y): x(x), y(y){}
void read(){
scanf("%lf %lf", &x, &y);
}
P operator -(P p){
return P(x - p.x, y - p.y);
}
P operator *(double p){
return P(x * p, y * p);
}
double dot(P p){
return x * p.x + y * p.y;
}
double det(P p){
return x * p.y - y * p.x;
}
};

int n, m;
P A[maxn], B[maxn];

//将两个凸包分别排成逆时针顺序
void AntiClockWise(P *A, int n){
for(int i = 0; i < n - 2; ++i){
if((A[i+1] - A[i]).det(A[i+2] - A[i]) > eps) return;
else if((A[i+1] - A[i]).det(A[i+2] - A[i]) < -eps){
reverse(A, A + n);
return;
}
}
}

//计算 a b 两点之间的距离
double dist(P a, P b){
double x = a.x - b.x, y = a.y - b.y;
return sqrt(x * x + y * y);
}

//计算点 a 到线段 bc 的距离
double distPL(P a, P b, P c){
if(dist(b, c) < eps) return dist(a, c);
if((a - b).dot(c - b) < -eps) return dist(a, b);
if((a - c).dot(b - c) < -eps) return dist(a, c);
return fabs((a - c).det(b - c) / dist(b, c));
}

//计算线段 ab 和 cd 之间的最小距离
double distLL(P a, P b, P c, P d){
return min(min(distPL(c, a, b), distPL(d, a, b)), min(distPL(a, c, d), distPL(b, c, d)));
}

double solve(){
int it0 = 0, it1 = 0;
for(int i = 0; i < n; ++i){//找到第一个凸包y值最小的点
if(A[i].y < A[it0].y) it0 = i;
}
for(int i = 0; i < m; ++i){//找到第二个凸包y值最大的点
if(B[i].y > B[it1].y) it1 = i;
}
A
= A[0], B[m] = B[0];//将凸包首尾相接,方便旋转

double res = inf;
for(int i = 0
bbf4
; i < n; ++i){
while((B[it1] - A[it0]).det(A[it0+1] - A[it0]) - (B[it1 + 1] - A[it0]).det(A[it0+1] - A[it0]) > eps)
it1 = (it1 + 1) % m;
res = min(res, distLL(A[it0], A[it0+1], B[it1], B[it1+1]));
it0 = (it0 + 1) % n;
}

return res;
}

int main(){
while(scanf("%d %d", &n, &m) == 2){
if(n == 0 && m == 0) break;

for(int i = 0; i < n; ++i){
A[i].read();
}
for(int i = 0; i < m; ++i){
B[i].read();
}

AntiClockWise(A, n);
AntiClockWise(B, m);

printf("%.5f\n", solve());
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: