zoukankan      html  css  js  c++  java
  • 【poj3608】 Bridge Across Islands

    http://poj.org/problem?id=3608 (题目链接)

    题意

      求两凸包间最短距离

    Solution

      难写难调,旋转卡壳,还真是卡死我了。

      先分别选出两凸包最上点和最下点,从这两点开始向逆时针方向旋转卡壳。用叉乘判断是否旋转旋转,具体操作跟求凸包直径差不多。

    poj discuss蒯下来的数据制造器:

    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    
    struct point{double x,y;};
    struct polygon
    {
        int n;
        point data[10];
    };
    #define N   16
    polygon p[N]={
        {4,{{0,0},{-1,0},{-1,-1},{0,-1}}},
        {4,{{2,0},{2,-1},{3,-1},{3,0}}},
        {4,{{247,208},{247,235},{375,235},{375,208}}},
        {3,{{85 ,101},{116 ,168},{168 ,103}}},
        {3,{{131 ,189},{216 ,148},{196 ,209}}},
        {3,{{180 ,127},{246 ,127},{202 ,144}}},
        {3,{{226 ,201},{297 ,201},{242 ,151}}},
        {3,{{42 ,225},{61 ,261},{100,222}}},
        {3,{{84 ,261},{99 ,246},{102,260}}},
        {3,{{72,309},{157,224},{167,309}}},
        {3,{{170,221},{229,221},{199,245}}},
        {3,{{190,90},{153,47},{225,108}}},
        {3,{{165,230},{168,242},{172,233}}},
        {6,{{143,146},{133,156},{138,170},{150,173},{161,166},{161,152}}},
        {5,{{109,208},{100,236},{111,253},{122,250},{161,206}}},
        {6,{{177,273},{174,309},{202,377},{417,375},{490,270},{268,239}}}
        };
    int main()
    {
        srand(time(NULL));
        //freopen("aaa.in","w",stdout);
        int i=0,j=0,k,num=0;
        while (i==j) i=rand()%N,j=rand()%N;
        num++;
        //if(num>35||num<=33)continue;
        printf("%d %d
    ",p[i].n,p[j].n);
        for(k=0;k<p[i].n;k++)
            printf("%lf %lf
    ",p[i].data[k].x,p[i].data[k].y);
        for(k=0;k<p[j].n;k++)
            printf("%lf %lf
    ",p[j].data[k].x,p[j].data[k].y);
        printf("0 0
    ");
        return 0;
    }
    

    代码

    // poj3608
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<map>
    #define esp 1e-8
    #define inf 2147483640
    #define LL long long
    #define Pi acos(-1.0)
    #define free(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout);
    using namespace std;
    inline LL getint() {
        LL x=0,f=1;char ch=getchar();
        while (ch>'9' || ch<'0') {if (ch=='-') f=-1;ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    
    const int maxn=10010;
    struct point {
        double x,y;
        point() {};
        point (double _x,double _y):x(_x),y(_y){}
        friend point operator - (const point &a,const point &b) {
            point x;
            x.x=a.x-b.x;x.y=a.y-b.y;
            return x;
        }
    }p1[maxn],p2[maxn],p0;
    int sn[maxn],sm[maxn],n,m;
    
    double cross(point p0,point p1,point p2) { //叉乘
        return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
    }
    double dis(point a,point b) { //点a与点b之间的距离
        return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    }
    bool cmp(point a,point b) { //极角排序
        double t=cross(p0,a,b);
        if (t<0) return 0;
        if (t>0) return 1;
        return dis(p0,a)<dis(p0,b);
    }
    int dcmp(double x) { //double比较
        return fabs(x)<esp ? 0 : (x>0 ? 1 : -1);
    }
    int Graham(int n,point *p) { //求凸包
        int k=1,top=2;
        for (int i=2;i<=n;i++)
            if (p[i].x==p[k].x ? p[i].y<p[k].y : p[i].x<p[k].x) k=i;
        p0=p[k];p[k]=p[1];p[1]=p0;
        sort(p+2,p+1+n,cmp);
        for (int i=3;i<=n;i++) {
            while (top>1 && cross(p[top-1],p[top],p[i])<=0) top--;
            p[++top]=p[i];
        }
        return top;
    }
    double pldis(point a,point b,point c) { //点a到线段bc的最短距离
        point s(a-b),t(c-b);
        if (s.x*t.x+s.y*t.y<0) return dis(a,b);
        s=(a-c);t=(b-c);
        if (s.x*t.x+s.y*t.y<0) return dis(a,c);
        return fabs(cross(a,b,c))/dis(b,c);
    }
    double lldis(point a,point b,point c,point d) { //线段ab与线段cd的最短距离
        return min(min(pldis(a,c,d),pldis(b,c,d)),min(pldis(c,a,b),pldis(d,a,b)));
    }
    double RC(point *pl,point *pr,int p,int q,int n,int m) { //旋转卡壳
        double tmp,minl=1e90;
        pl[n+1]=pl[1];pr[m+1]=pr[1];
        for (int i=1;i<=n;i++) {
            while ((tmp=cross(pl[p+1],pr[q+1],pl[p])-cross(pl[p+1],pr[q],pl[p]))>esp) q=q%m+1;
            if (tmp<-esp) minl=min(minl,pldis(pr[q],pl[p],pl[p+1]));
            else minl=min(minl,lldis(pl[p],pl[p+1],pr[q],pr[q+1]));
            p=p%n+1;
        }
        return minl;
    }
    void clocksort() { //逆时针排序
        p0.x=0;p0.y=0;
        for (int i=1;i<=n;i++) {p0.x+=p1[i].x;p0.y+=p1[i].y;}
        p0.x/=n;p0.y/=n;
        sort(p1+1,p1+1+n,cmp);
        p0.x=0;p0.y=0;
        for (int i=1;i<=m;i++) {p0.x+=p2[i].x;p0.y+=p2[i].y;}
        p0.x/=m;p0.y/=m;
        sort(p2+1,p2+1+m,cmp);
    }
    int main() {
        while (scanf("%d%d",&n,&m)!=EOF && n && m) {
            for (int i=1;i<=n;i++) scanf("%lf%lf",&p1[i].x,&p1[i].y);
            for (int i=1;i<=m;i++) scanf("%lf%lf",&p2[i].x,&p2[i].y);
            n=Graham(n,p1);
            m=Graham(m,p2);
            //clocksort();
            int l=1,r=1;
            for (int i=1;i<=n;i++) if (dcmp(p1[i].y-p1[l].y)<0) l=i; //最下点
            for (int i=1;i<=m;i++) if (dcmp(p2[i].y-p2[r].y)>0) r=i; //最上点
            printf("%.5lf
    ",min(RC(p1,p2,l,r,n,m),RC(p2,p1,r,l,m,n)));
        }
        return 0;
    }
    

      

  • 相关阅读:
    R语言初涉
    Android源码大全
    Centos关闭防火墙
    Java开发常用下载的网址
    linux下解压命令大全
    Android常见布局问题
    配置Nutch模拟浏览器以绕过反爬虫限制
    Nutch的发展历程
    用三层交换机当路由器——最复杂的网络拓扑结构
    Ant 简易教程
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/5914389.html
Copyright © 2011-2022 走看看