Description
Thousands of thousands years ago there was a small kingdom located in the middle of the Pacific Ocean. The territory of the kingdom consists two separated islands. Due to the impact of the ocean current, the shapes of both the islands became convex polygons. The king of the kingdom wanted to establish a bridge to connect the two islands. To minimize the cost, the king asked you, the bishop, to find the minimal distance between the boundaries of the two islands.
Input
The input consists of several test cases.
Each test case begins with two integers N, M. (3 ≤ N, M ≤ 10000)
Each of the next N lines contains a pair of coordinates, which describes the position of a vertex in one convex polygon.
Each of the next M lines contains a pair of coordinates, which describes the position of a vertex in the other convex polygon.
A line with N = M = 0 indicates the end of input.
The coordinates are within the range [-10000, 10000].
Output
For each test case output the minimal distance. An error within 0.001 is acceptable.
Sample Input
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
Sample Output
1.00000
分析:
用了一上午,终于A了
题解:
http://blog.csdn.net/acm_zl/article/details/12111657
我在这里再进一步解释一下代码:
这是第一个复杂一点函数,把一个凸包中的所有点变成逆时针
cross是叉积(sin),a–>b顺时针转结果是负,a–>b逆时针转结果是正
这里就是主体的计算部分了,想要强调的一点是,
p[]是数组,传入的是指针,所以不用写取地址符就可以更改p的值
solve中的第一小部分,分别找p中最靠左的点和q中最靠右的点
这一部分是最难的了:
一直奇怪为什么这里的Cross为什么不加fabs
大概是因为我们进行了两遍solve,一定有一遍让两个三角形的面积都是两个逆时针转动的向量做Cross
Cross逆时针转时值为正
那么Cross(q[mq+1]-p[mp+1],p[mp]-p[mp+1])-Cross(q[mq]-p[mp+1],p[mp]-p[mp+1]))>eps
表示mq+1代表的三角形面积大
跳出while循环的条件很明显是t<=eps
如果t<-eps,说明卡壳的两条平行线一条与边重合,一条只过一点
(为什么不是 < eps? 因为若两个面积相等,那么t < eps,但这种情况是要归到下面的)
t==eps
平行线恰好是两个多边形的边
我们就把ta三个一组拆成上面的情况,
最后返回最小值
点对边的情况
dis传入的先是边的两个端点,之后是一个单点
四种情况
注意,dis传入的先是边的两个端点,之后是一个单点,所以ds在调用dis的时候不要传错参数
再多说一句,’==’也是可以重载的,返回值是bool
这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;
const double eps=1e-10;
const double INF=1e10;
int n,m;
struct node{
double x,y;
node (double xx=0,double yy=0)
{
x=xx;y=yy;
}
};
node p[10005],q[10005];
double mn(double a,double b){return a>b?b:a;}
int dcmp(double x)
{
if (fabs(x)<eps) return 0;
else if (x>0) return 1;
else return -1;
}
node operator +(const node &a,const node &b){return node(a.x+b.x,a.y+b.y);}
node operator -(const node &a,const node &b){return node(a.x-b.x,a.y-b.y);}
node operator *(const node &a,const double &b){return node(a.x*b,a.y*b);}
node operator /(const node &a,const double &b){return node(a.x/b,a.y/b);}
bool operator ==(const node &a,const node &b){
return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
}
double Cross(node x,node y){return x.x*y.y-x.y*y.x;}
double Dot(node x,node y){return x.x*y.x+x.y*y.y;}
void red(node a[],int n,node b[],int m)
{
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);
}
void change(node a[],int b)
{
for (int i=0;i<b/2;i++)
{
node t=a[i];
a[i]=a[b-i-1];
a[b-i-1]=t;
}
return;
}
void work(node p[],int n,node q[],int m)
{
int i;
for (i=0;i<n-2;i++)
if (dcmp(Cross(p[i+1]-p[i],p[i+2]-p[i]))>0) break;
else if (dcmp(Cross(p[i+1]-p[i],p[i+2]-p[i]))<0)
{
change(p,n);
break;
}
for (i=0;i<m-2;i++)
if (dcmp(Cross(q[i+1]-q[i],q[i+2]-q[i]))>0) break;
else if (dcmp(Cross(q[i+1]-q[i],q[i+2]-q[i]))<0)
{
change(q,m);
break;
}
}
double len(node a){return sqrt(Dot(a,a));}
double dis(node a,node b,node p)
{
if (a==b) return len(a-p);
node v1=b-a,v2=p-a,v3=p-b;
if (dcmp(Dot(v1,v2))<0) return len(v2);
if (dcmp(Dot(v1,v3))>0) return len(v3);
return fabs(Cross(v1,v2))/len(v1);
}
double ds(node a,node b,node c,node d)
{
return mn(mn(dis(a,b,c),dis(a,b,d)),
mn(dis(c,d,a),dis(c,d,b)));
}
double solve(node p[],int n,node q[],int m)
{
int i,mp=0,mq=0;
double ans=INF,t;
for (i=0;i<n;i++)
if (p[i].y<p[mp].y) mp=i;
for (i=0;i<m;i++)
if (q[i].y>q[mq].y) mq=i;
p[n]=p[0];
q[m]=q[0];
for (i=0;i<n;i++)
{
while ((t=Cross(q[mq+1]-p[mp+1],p[mp]-p[mp+1])-Cross(q[mq]-p[mp+1],p[mp]-p[mp+1]))>eps)
mq=(mq+1)%m;
if (t<-eps)
ans=mn(ans,dis(p[mp],p[mp+1],q[mq]));
else ans=mn(ans,ds(q[mq],q[mq+1],p[mp],p[mp+1]));
mp=(mp+1)%n;
}
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
while (n&&m)
{
red(p,n,q,m);
work(p,n,q,m);
double a,b;
a=solve(p,n,q,m);
b=solve(q,m,p,n);
printf("%0.5lf
",mn(a,b));
scanf("%d%d",&n,&m);
}
return 0;
}