题目链接:http://poj.org/problem?id=3608
题意:求两个多边形的最近对踵点对。(已知两个多边形不相交)
思路:模板。
View Code
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define min(x,y) ((x)<(y)?(x):(y))
using namespace std;
struct point
{
double x,y;
point(){}
point(double _x,double _y)
{
x=_x;
y=_y;
}
void get()
{
scanf("%lf%lf",&x,&y);
}
};
const double EPS=1e-8;
const int MAX=10005;
point p[MAX],q[MAX],p1[MAX],q1[MAX],temp;
int n,m,N,M;
int DB(double x)
{
if(x>EPS) return 1;
if(x<-EPS) return -1;
return 0;
}
double Dis(point a,point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
//判断p在向量ab的哪一侧
//右侧:返回正值
//左侧:返回负值
//在向量ab上返回0
double cross(point a,point b,point p)
{
return (b.x-a.x)*(p.y-a.y)-(b.y-a.y)*(p.x-a.x);
}
int cmp(point a,point b)
{
double x=Dis(a,temp),y=Dis(b,temp);
int flag=DB(cross(temp,a,b));
if(flag) return flag==1;
return DB(x-y)<=0;
}
void Graham(point p[],int n,point q[],int &m)
{
point t;
int i,k=0,a,b;
for(i=1;i<n;i++)
{
a=DB(p[i].y-p[k].y);
b=DB(p[i].x-p[k].x);
if(a==-1||!a&&b==-1) k=i;
}
if(k!=0) t=p[0],p[0]=p[k],p[k]=t;
temp=p[0];
sort(p+1,p+n,cmp);
q[0]=p[0];
q[1]=p[1];
p[n]=p[0];
m=2;
for(i=2;i<=n;i++)
{
while(m>1&&DB(cross(q[m-2],q[m-1],p[i]))<=0) m--;
q[m++]=p[i];
}
m--;
}
double getAngle(point a1,point a2,point b1,point b2)
{
point t;
t.x=b2.x-b1.x+a1.x;
t.y=b2.y-b1.y+a1.y;
return cross(a1,a2,t);
}
double Dis1(point a,point p,point q)
{
double t1=(q.x-p.x)*(a.x-p.x)+(q.y-p.y)*(a.y-p.y);
double t2=(p.x-q.x)*(a.x-q.x)+(p.y-q.y)*(a.y-q.y);
if(DB(t1)!=-1&&DB(t2)!=-1) return fabs(cross(a,p,q))/Dis(p,q);
return min(Dis(a,p),Dis(a,q));
}
//凸包最近对踵点
double calMinDis(point p[],int n,point q[],int m)
{
int sp=0,sq=0,i,a,b,tp,tq;
double ans,flag;
for(i=0;i<n;i++)
{
a=DB(p[i].y-p[sp].y);
b=DB(p[i].x-p[sp].x);
if(a==-1||!a&&b==-1) sp=i;
}
for(i=0;i<m;i++)
{
a=DB(q[i].y-q[sq].y);
b=DB(q[i].x-q[sq].x);
if(a==1||!a&&b==1) sq=i;
}
ans=Dis(p[sp],q[sq]);
tp=sp;
tq=sq;
do
{
flag=DB(getAngle(p[sp],p[(sp+1)%n],q[sq],q[(sq+1)%m]));
if(flag==0)
{
ans=min(ans,Dis1(p[sp],q[sq],q[(sq+1)%m]));
ans=min(ans,Dis1(p[(sp+1)%n],q[sq],q[(sq+1)%m]));
ans=min(ans,Dis1(q[sq],p[sp],p[(sp+1)%n]));
ans=min(ans,Dis1(q[(sq+1)%m],p[sp],p[(sp+1)%n]));
sp=(sp+1)%n;
sq=(sq+1)%m;
}
else if(flag==-1)
{
ans=min(ans,Dis1(q[sq],p[sp],p[(sp+1)%n]));
sp=(sp+1)%n;
}
else
{
ans=min(ans,Dis1(p[sp],q[sq],q[(sq+1)%m]));
sq=(sq+1)%m;
}
}while(tp!=sp||tq!=sq);
return ans;
}
int main()
{
while(scanf("%d%d",&n,&m),n||m)
{
int i;
for(i=0;i<n;i++) p[i].get();
for(i=0;i<m;i++) q[i].get();
Graham(p,n,p1,N);
Graham(q,m,q1,M);
double ans=calMinDis(p1,N,q1,M);
printf("%.5lf\n",ans);
}
return 0;
}