题目:http://poj.org/problem?id=3608
题意:给你连个凸包,求这两个凸包边界的最短距离
分析:经典题目,旋转卡壳来搞就行,具体细节太多,我套了模板,改了个变量就过了,旋转卡壳这东西就是思想简单,细节复杂。。。
不知道这个模板是否是正确的,反正AC了T_T
代码:
#include<cmath> #include<cstdio> #include<iostream> #include<algorithm> using namespace std; const int mm=11111; const double eps=1e-16; typedef double diy; struct point { diy x,y; point(){} point(diy _x,diy _y):x(_x),y(_y){} }g1[mm],g2[mm]; point Vector(point s,point t) { return point(t.x-s.x,t.y-s.y); } diy DotProduct(point P,point Q) { return P.x*Q.x+P.y*Q.y; } diy CrossProduct(point P,point Q) { return P.x*Q.y-P.y*Q.x; } diy MultiCross(point P,point Q,point R) { return CrossProduct(Vector(Q,P),Vector(Q,R)); } diy MultiDot(point P,point Q,point R) { return DotProduct(Vector(Q,P),Vector(Q,R)); } double Dis(point P,point Q) { return sqrt(1.0*(P.x-Q.x)*(P.x-Q.x)+1.0*(P.y-Q.y)*(P.y-Q.y)); } double PointSegDis(point P,point Q,point R) { if(MultiDot(P,Q,R)<-eps)return Dis(Q,R); if(MultiDot(Q,P,R)<-eps)return Dis(P,R); return fabs(MultiCross(P,Q,R)/Dis(P,Q)); } double SegDis(point P,point Q,point U,point V) { return min(min(PointSegDis(P,Q,U),PointSegDis(P,Q,V)), min(PointSegDis(U,V,P),PointSegDis(U,V,Q))); } double RotateCaliperConvexDis(point *p,point *q,int n,int m) { int i,u,v; double ret=1e99; p[n]=p[0],q[m]=q[0]; for(u=i=0;i<n;++i) if(p[u].y>p[i].y)u=i; for(v=i=0;i<m;++i) if(q[v].y<q[i].y)v=i; for(i=0;i<n;++i) { while(MultiCross(p[u],q[v],p[u+1])<MultiCross(p[u],q[v+1],p[u+1]))v=(v+1)%m; ret=min(ret,SegDis(p[u],p[u+1],q[v],q[v+1])); u=(u+1)%n; } return ret; } void AntiClockwise(point *p,int n) { for(int i=1;i<n-1;++i) if(MultiCross(p[i-1],p[i],p[i+1])<0)return; for(int i=0;i<(n>>1);++i) swap(p[i],p[n-i-1]); } int main() { int i,n,m; while(scanf("%d%d",&n,&m),n+m) { for(i=0;i<n;++i) scanf("%lf%lf",&g1[i].x,&g1[i].y); for(i=0;i<m;++i) scanf("%lf%lf",&g2[i].x,&g2[i].y); AntiClockwise(g1,n); AntiClockwise(g2,m); printf("%.5lf\n",RotateCaliperConvexDis(g1,g2,n,m)); } return 0; }