题意
给你两个凸多边形 问你两凸多边形的最近距离
思路
找到凸包 p 的 y 值最小点 yminP 和 q 的 y 值最大点ymaxQ
枚举P[yminP]-P[yminP + 1]这条边 与Q[ymaxQ]Q[ymaxQ]旋转卡 每次找到最近后 min(四个点两条边的距离)
代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const double eps = 1e-8;
const double pi = acos(-1.0);
const double inf = 1.0 * 0x3f3f3f3f;
const int MaxN = 1e4 + 5;
int Top,n,m;
struct Point{
double x,y;
Point(double x = 0,double y = 0):x(x),y(y){}
}p[MaxN],q[MaxN],stack[MaxN],C;
typedef Point Vector;
int dcmp(double x){
if(fabs(x) < eps) return 0;
else return x < 0 ? -1:1;
}
Vector operator + (Vector A,Vector B){ return Vector(A.x+B.x,A.y+B.y);}
Vector operator - (Vector A,Vector B){ return Vector(A.x-B.x,A.y-B.y);}
Vector operator * (Vector A,double p){ return Vector(A.x*p,A.y*p);}
bool operator == (const Point &a,const Point &b){
return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0;
}
double Dot(Vector A,Vector B){ return A.x*B.x+A.y*B.y;}
double Cross(Vector A,Vector B){ return A.x*B.y-A.y*B.x;}
double dis(Point A,Point B){
return sqrt((A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y));
}
double compare(Point a,Point b,Point c){
return Cross(c - a,c - b);
}
bool cmp(Point a,Point b){
if(dcmp(compare(a,b,C)) == 0) return dis(a,C) < dis(b,C);
return dcmp(compare(a,b,C)) > 0;
}
void Graham_scan(Point p[]){
int i , k = 0;
Top = 2;
for(i = 1;i < n; i++){
if(p[i].y < p[k].y || (p[i].y == p[k].y && p[i].x < p[k].x)) k = i;
}
swap(p[0],p[k]);
C = p[0];
sort(p + 1,p + n,cmp);
stack[0] = p[0];
stack[1] = p[1];
stack[2] = p[2];
for(int i = 3;i < n; i++){
while(Top > 1 && compare(p[i],stack[Top],stack[Top - 1]) >= 0) Top--;
stack[++Top] = p[i];
}
//[0,Top]
}
bool clockwise(Point a[],int n){//?顺时针
double ans = 0.0;
for(int i = 1;i <= n - 2; i++){
ans += Cross(a[i] - a[0],a[i + 1] - a[0]);
}
if(dcmp(ans) > 0) return false;
return true;
}
//C到线段AB的最短距离
double Getdist(Point A,Point B,Point C){
if(dcmp(dis(A,B)) == 0) return dis(A,C);
else if(dcmp(Dot(C - A,B - A)) < 0) return dis(A,C);
else if(dcmp(Dot(C - B,A - B)) < 0) return dis(B,C);
return fabs(Cross(C - A,B - A) / dis(A,B));
}
//线段AB 到 线段CD 四对点到线段的最短距离
double Mindist(Point A,Point B,Point C,Point D){
return min(min(Getdist(A,B,C),Getdist(A,B,D)),min(Getdist(C,D,A),Getdist(C,D,B)));
}
double RotatingCalipers(Point P[],int n,Point Q[],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 res = inf;
for(int i = 0;i < n; i++){
while(Cross(P[yminP + 1] - P[yminP],Q[ymaxQ + 1] - P[yminP]) - Cross(P[yminP + 1] - P[yminP],Q[ymaxQ] - P[yminP]) > 0){
ymaxQ = (ymaxQ + 1) % m;
}
res = min(res,Mindist(P[yminP],P[yminP + 1],Q[ymaxQ],Q[ymaxQ + 1]));
yminP = (yminP + 1) % n;
}
return res;
}
int main()
{
while(~scanf("%d%d",&n,&m) && n && m){
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);
}
if(clockwise(p,n)) reverse(p,p + n);
if(clockwise(q,m)) reverse(q,q + m);
double ans = RotatingCalipers(p,n,q,m);
printf("%.5f\n",ans);
}
return 0;
}