WA了好多次
说一下错误
第一个地方是旋转卡壳是要进行两次的
第二个地方其实也不算错误,应该是程序运行的精度问题
在下面这部分程序中
//while((tmp=(p[(miny+1)%n]-p[miny])^(p[maxy]-p[(maxy+1)%m]))<-eps) maxy=(maxy+1)%m;//只要在向量miny-miny+1右侧则说明在向对踵点对的方向靠
while((tmp=Get_angle(p[miny],p[miny+1],q[maxy],q[maxy+1]))<-eps) maxy=(maxy+1)%m;
注释部分其实和非注释部分的程序转换过来是一样的,但运行结果却不一样
可能在同一个语句中不能进行太多的运算,要不然有可能会导致精度降低
总结就是以后在同一个语句中不要进行过多的运算,要分部分赋值
//最近点对和最远点对产生在有向平行切线上,将一条边平行过去,然后判断
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include<algorithm>
using namespace std;
const double eps=1e-8;
struct Point {
double x,y;
Point (){}
Point (double xx,double yy) {x=xx;y=yy;}
Point operator -(const Point b)const {return Point(x-b.x,y-b.y);}
double operator ^(const Point b)const {return x*b.y-y*b.x;}
double operator *(const Point &b)const{
return x*b.x + y*b.y;
}
};
struct Line {
Point s,e;
double angle;
Line(){}
Line(Point ss,Point ee) {s=ss;e=ee;}
};
Point p[10005],q[10005],list[10005];
int n,m,top,miny,maxy;
double dist(Point a,Point b) {
return sqrt((b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y));
}
//求点到线段距离,不是点到直线距离
double pointtoseg(Point P,Point b,Point c){
/*Line s=Line(b,c);
Point mid;
double t=(p-s.s)*(s.e-s.s)/((s.e-s.s)*(s.e-s.s));//s.s到垂点的距离/s.s到s.e的距离
double ans;
if(t>=0 && t<=1) {
mid.x=s.s.x+(s.e.x-s.s.x)*t;
mid.y=s.s.y+(s.e.y-s.s.y)*t;
ans=dist(p,mid);
}
else {
if(dist(p,s.s)<dist(p,s.e)) ans=dist(p,s.s);
else ans=dist(p,s.e);
}
printf("%lf\n",ans);
return ans;*/
Point result;
Line L=Line(b,c);
double t = ((P-L.s)*(L.e-L.s))/((L.e-L.s)*(L.e-L.s));
if(t >=0 && t <= 1)
{
result.x = L.s.x + (L.e.x - L.s.x)*t;
result.y = L.s.y + (L.e.y - L.s.y)*t;
}
else
{
if(dist(P,L.s) < dist(P,L.e))
result = L.s;
else result = L.e;
}
return dist(result,P);
}
double segtoseg(Point a,Point b,Point c,Point d){
double ans1=min(pointtoseg(a,c,d),pointtoseg(b,c,d));
double ans2=min(pointtoseg(c,a,b),pointtoseg(d,a,b));
return min(ans1,ans2);
}
int cmp(Point a,Point b) {//逆时针
double tmp=(a-list[0])^(b-list[0]);
if(tmp == 0) return dist(a,list[0]) - dist(b,list[0]) <-eps;
else return tmp>0;
}
void Graham(Point* p,Point* stack,int n){
int k=0;
for(int i=0;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]);
sort(p+1,p+n,cmp);
if(n<=2){
for(int i=0;i<n;i++) stack[i]=p[i];
top=n;
return;
}
stack[0]=p[0]; stack[1]=p[1];
top=2;
for(int i=2;i<n;i++){
while(top>=2 && ((stack[top-1]-stack[top-2])^(p[i]-stack[top-2]))<eps) top--;
stack[top++]=p[i];
}
}
double Get_angle(Point a1,Point a2,Point b1,Point b2)
{
return (a2-a1)^(b1-b2);
}
double rotating(Point* p,int n,Point* q,int m){
miny=0,maxy=0;
for(int i=0;i<n;i++) {
if(p[i].y<p[miny].y) miny=i;
}
for(int i=0;i<m;i++) {
if(q[i].y>q[maxy].y) maxy=i;
}
double ans=dist(p[miny],q[maxy]);
for(int i=0;i<n;i++){
double tmp;
//while((tmp=(p[(miny+1)%n]-p[miny])^(p[maxy]-p[(maxy+1)%m]))<-eps) maxy=(maxy+1)%m;//只要在向量miny-miny+1右侧则说明在向对踵点对的方向靠
while((tmp=Get_angle(p[miny],p[miny+1],q[maxy],q[maxy+1]))<-eps) maxy=(maxy+1)%m;
if(fabs(tmp)<eps) ans=min(ans,segtoseg(p[miny],p[(miny+1)%n],q[maxy],q[(maxy+1)%m]));
else ans=min(ans,pointtoseg(q[maxy],p[miny],p[(miny+1)%n]));
miny=(miny+1)%n;
}
return ans;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif // ONLINE_JUDGE
while(scanf("%d%d",&n,&m)) {
if(n==0 && m==0) break;
//顺时针排列的点
miny=0,maxy=0;
for(int i=0;i<n;i++) {
scanf("%lf%lf",&list[i].x,&list[i].y);
}
Graham(list,p,n);
n=top;
for(int i=0;i<m;i++) {
scanf("%lf%lf",&list[i].x,&list[i].y);
}
Graham(list,q,m);
m=top;
p[n]=p[0];
q[m]=q[0];
printf("%.5f\n",min(rotating(p,n,q,m),rotating(q,m,p,n)));
}
return 0;
}