• POJ 3608 旋转卡壳


    题意:

    求两个凸包的最近距离。

    题解:

    原来旋转卡壳这么暴力。。我以前一直以为是O(n)的。。。

    画画图,用叉积判断下旋转角度就行了~

    View Code
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <algorithm>
      6 #include <cmath>
      7 
      8 #define N 22222
      9 #define PI 3.14159265358979
     10 #define EPS 1e-7
     11 
     12 using namespace std;
     13 
     14 struct PO
     15 {
     16     double x,y;
     17 }p1[N],p2[N],o;
     18 
     19 int n,m,top1,top2,stk1[N],stk2[N];
     20 
     21 inline int doublecmp(double x)
     22 {
     23     if(x>EPS) return 1;
     24     else if(x<-EPS) return -1;
     25     return 0;
     26 }
     27 
     28 inline bool cmp(const PO &a,const PO &b)
     29 {
     30     if(doublecmp(a.x-b.x)==0) return a.y<b.y;
     31     return a.x<b.x;
     32 }
     33 
     34 inline void read()
     35 {
     36     for(int i=1;i<=n;i++) scanf("%lf%lf",&p1[i].x,&p1[i].y);
     37     for(int i=1;i<=m;i++) scanf("%lf%lf",&p2[i].x,&p2[i].y);
     38 }
     39 
     40 inline PO operator +(PO a,PO b)
     41 {
     42     PO c;
     43     c.x=a.x+b.x;
     44     c.y=a.y+b.y;
     45     return c;
     46 }
     47 
     48 inline PO operator -(PO a,PO b)
     49 {
     50     PO c;
     51     c.x=a.x-b.x;
     52     c.y=a.y-b.y;
     53     return c;
     54 }
     55 
     56 inline double dot(PO &a,PO &b,PO &c)
     57 {
     58     return (b.x-a.x)*(c.x-a.x)+(b.y-a.y)*(c.y-a.y);
     59 }
     60 
     61 inline double cross(PO &a,PO &b,PO &c)
     62 {
     63     return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
     64 }
     65 
     66 inline double getlen(PO &a)//向量的模 
     67 {
     68     return sqrt(a.x*a.x+a.y*a.y);
     69 }
     70 
     71 inline PO getty(PO b,PO a)//投影向量 
     72 {
     73     PO res=a;
     74     double k=dot(o,a,b)/(getlen(a)*getlen(a));
     75     res.x*=k; res.y*=k;
     76     return res;
     77 }
     78 
     79 inline double getangle(PO &a,PO &b,PO&c,PO &d)
     80 {
     81     PO t=c+(a-d);
     82     return cross(a,b,t);
     83 }
     84 
     85 inline PO rotate(PO a,double hd)
     86 {
     87     PO c;
     88     c.x=a.x*cos(hd)-a.y*sin(hd);
     89     c.y=a.x*sin(hd)+a.y*cos(hd);
     90     return c;
     91 }
     92 
     93 inline double getdis(PO &a,PO &b)
     94 {
     95     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
     96 }
     97 
     98 inline double getdis_ps(PO &a,PO &b,PO &c)
     99 {
    100     PO t=c-b;
    101     t=rotate(t,-PI*0.5);
    102     PO s=c-a;;
    103     PO ty=getty(s,t);
    104     s=a+ty;
    105     if(doublecmp(dot(s,b,c))<=0) return getlen(ty);
    106     else return min(getdis(a,b),getdis(a,c));
    107 }
    108 
    109 inline void graham(PO *p,int *stk,int &top,int gs)
    110 {
    111     sort(p+1,p+1+gs,cmp);
    112     top=-1;
    113     stk[++top]=1; stk[++top]=2;
    114     for(int i=3;i<=gs;i++)
    115     {
    116         while(top>=1&&doublecmp(cross(p[stk[top-1]],p[stk[top]],p[i]))<=0) top--;
    117         stk[++top]=i;
    118     }
    119     int tmp=top;
    120     for(int i=gs-1;i>=1;i--)
    121     {
    122         while(top>=tmp+1&&doublecmp(cross(p[stk[top-1]],p[stk[top]],p[i]))<=0) top--;
    123         stk[++top]=i;
    124     }
    125 }
    126 
    127 inline double rotating_calipers()
    128 {
    129     int s1=0,s2=0;
    130     for(int i=1;i<top1;i++)
    131         if(doublecmp(p1[stk1[i]].y-p1[stk1[s1]].y)<0||(doublecmp(p1[stk1[i]].y-p1[stk1[s1]].y)==0)&&doublecmp(p1[stk1[i]].x-p1[stk1[s1]].x)<0) s1=i;
    132     for(int i=1;i<top2;i++)
    133         if(doublecmp(p2[stk2[i]].y-p2[stk2[s2]].y)>0||(doublecmp(p2[stk2[i]].y-p2[stk2[s2]].y)==0)&&doublecmp(p2[stk2[i]].x-p2[stk2[s2]].x)>0) s2=i;
    134     int t1=s1,t2=s2;
    135     double ans=getdis(p1[stk1[s1]],p2[stk2[s2]]);
    136     do
    137     {
    138         double af=getangle(p1[stk1[s1]],p1[stk1[(s1+1)%top1]],p2[stk2[s2]],p2[stk2[(s2+1)%top2]]);
    139         if(doublecmp(af)==0)//卡壳到两条边 
    140         {
    141             ans=min(ans,getdis_ps(p1[stk1[s1]],p2[stk2[s2]],p2[stk2[(s2+1)%top2]]));
    142             ans=min(ans,getdis_ps(p1[stk1[(s1+1)%top1]],p2[stk2[s2]],p2[stk2[(s2+1)%top2]]));
    143             ans=min(ans,getdis_ps(p2[stk2[s2]],p1[stk1[s1]],p1[stk1[(s1+1)%top1]]));
    144             ans=min(ans,getdis_ps(p2[stk2[(s2+1)%top2]],p1[stk1[s1]],p1[stk1[(s1+1)%top1]]));
    145             s1=(s1+1)%top1; s2=(s2+1)%top2;
    146         }
    147         else if(doublecmp(af)>0)//卡壳到第一个的边,第二个的点 
    148         {
    149             ans=min(ans,getdis_ps(p2[stk2[s2]],p1[stk1[s1]],p1[stk1[(s1+1)%top1]]));
    150             s1=(s1+1)%top1;
    151         }
    152         else//卡壳到第二个的边,第一个的点 
    153         {
    154             ans=min(ans,getdis_ps(p1[stk1[s1]],p2[stk2[s2]],p2[stk2[(s2+1)%top2]]));
    155             s2=(s2+1)%top2;
    156         }
    157     }while(t1!=s1||t2!=s2);
    158     return ans;
    159 }
    160 
    161 inline void go()
    162 {
    163     graham(p1,stk1,top1,n);
    164     graham(p2,stk2,top2,m);
    165     printf("%.5lf\n",rotating_calipers());
    166 }
    167 
    168 int main()
    169 {
    170     while(scanf("%d%d",&n,&m),n) read(),go();
    171     return 0;
    172 }

     这题太坑了,凸包写错了都能ac。。

    害得我下一道题直接粘的这个凸包,wa了一下午。。

  • 相关阅读:
    内蒙古草原之行
    【iOS开发笔记25/50】:正则表达式
    读书笔记:《写给大家看的设计书》
    【iOS开发笔记22/50】:恼人的a valid provisioning profile for this executable was not found错误
    【搞定GTD】打造高效的OmniFocus系统
    【iOS开发笔记24/50】调整UIImage的大小
    【iOS开发笔记26/50】我自己写的苹果应用程序XQViewer终于上架了,解决了一系列的问题,终于挺过来了
    桥牌笔记:双挤
    养成一个习惯需要几年,而毁掉一下习惯只需要一天
    使用SuperMemo背单词2000天,抓图纪念一下!
  • 原文地址:https://www.cnblogs.com/proverbs/p/2932711.html
Copyright © 2020-2023  润新知