码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 3608 Bridge Across Islands

时间:2015-03-07 17:13:02      阅读:152      评论:0      收藏:0      [点我收藏+]

标签:计算几何   旋转卡壳   凸包   

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;
}


POJ 3608 Bridge Across Islands

标签:计算几何   旋转卡壳   凸包   

原文地址:http://blog.csdn.net/lj94093/article/details/44117407

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!