zoukankan      html  css  js  c++  java
  • poj3502 恶心题

    巨恶心的一个题::>_<::

    题意:给出航班航线和大陆,找航线上距离大陆最远的某一点距离大陆边缘的距离

    标准算法:二分答案,从大陆边界向外扩展,扩展出来的面积会覆盖航线。找出航线上最后被覆盖的点即可。

    poj讨论版上还有人用模拟退火做的orz

    自己的YY算法:如图

    找出那些航线与大陆边界的交界点,这些交界点把航线又分成了若干线段。从这些线段上找点即可。

    这方法是好想可是不好写啊喂>_<

    全写完估计800行啊喂>_<

    不写了-_-||

    一开始还有脑洞地去求大陆的凸包,实际上那就错了= =。直接按顺序构造多边形即可

    上半成品:

      1 #include<vector>
      2 #include<list>
      3 #include<map>
      4 #include<set>
      5 #include<deque>
      6 #include<queue>
      7 #include<stack>
      8 #include<bitset>
      9 #include<algorithm>
     10 #include<functional>
     11 #include<numeric>
     12 #include<utility>
     13 #include<iostream>
     14 #include<sstream>
     15 #include<iomanip>
     16 #include<cstdio>
     17 #include<cmath>
     18 #include<cstdlib>
     19 #include<cctype>
     20 #include<string>
     21 #include<cstring>
     22 #include<cstdio>
     23 #include<cmath>
     24 #include<cstdlib>
     25 #include<ctime>
     26 #include<climits>
     27 #include<complex>
     28 #define mp make_pair
     29 #define pb push_back
     30 using namespace std;
     31 const double eps=1e-8;//精度
     32 const double pi=acos(-1.0);//π
     33 const double inf=1e20;//无穷大
     34 const int maxp=1111;//最大点数
     35 /*
     36     判断d是否在精度内等于0
     37 */
     38 
     39 bool cmp(double x,double y)
     40 {    return x<y;    }
     41 
     42 int dblcmp(double d)
     43 {
     44     if (fabs(d)<eps)return 0;
     45     return d>eps?1:-1;
     46 }
     47 /*
     48     求x的平方
     49 */
     50 inline double sqr(double x){return x*x;}
     51 /*
     52     点/向量
     53 */
     54 struct point
     55 {
     56     double x,y;
     57     int dis;        //inside(1) OR outside(0) OF the continent
     58     point(){}
     59     point(double _x,double _y):x(_x),y(_y){};
     60     //读入一个点
     61     void input()
     62     {
     63         scanf("%lf%lf",&x,&y);
     64     }
     65     //输出一个点
     66     void output()
     67     {
     68         printf("%.2f %.2f
    ",x,y);
     69     }
     70     //判断两点是否相等
     71     bool operator==(point a)const
     72     {
     73         return dblcmp(a.x-x)==0&&dblcmp(a.y-y)==0;
     74     }
     75     //判断两点大小
     76     bool operator<(point a)const
     77     {
     78         return dblcmp(a.x-x)==0?dblcmp(y-a.y)<0:x<a.x;
     79     }
     80     //点到源点的距离/向量的长度
     81     double len()
     82     {
     83         return hypot(x,y);
     84     }
     85     //点到源点距离的平方
     86     double len2()
     87     {
     88         return x*x+y*y;
     89     }
     90     //两点间的距离
     91     double distance(point p)
     92     {
     93         return hypot(x-p.x,y-p.y);
     94     }
     95     //向量加
     96     point add(point p)
     97     {
     98         return point(x+p.x,y+p.y);
     99     }
    100     //向量减
    101     point sub(point p)
    102     {
    103         return point(x-p.x,y-p.y);
    104     }
    105     //向量乘
    106     point mul(double b)
    107     {
    108         return point(x*b,y*b);
    109     }
    110     //向量除
    111     point div(double b)
    112     {
    113         return point(x/b,y/b);
    114     }
    115     //点乘
    116     double dot(point p)
    117     {
    118         return x*p.x+y*p.y;
    119     }
    120     //叉乘
    121     double det(point p)
    122     {
    123         return x*p.y-y*p.x;
    124     }
    125     //XXXXXXX
    126     double rad(point a,point b)
    127     {
    128         point p=*this;
    129         return fabs(atan2(fabs(a.sub(p).det(b.sub(p))),a.sub(p).dot(b.sub(p))));
    130     }
    131     //截取长度r
    132     point trunc(double r)
    133     {
    134         double l=len();
    135         if (!dblcmp(l))return *this;
    136         r/=l;
    137         return point(x*r,y*r);
    138     }
    139     //左转90度
    140     point rotleft()
    141     {
    142         return point(-y,x);
    143     }
    144     //右转90度
    145     point rotright()
    146     {
    147         return point(y,-x);
    148     }
    149     //绕点p逆时针旋转angle角度
    150     point rotate(point p,double angle)
    151     {
    152         point v=this->sub(p);
    153         double c=cos(angle),s=sin(angle);
    154         return point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c);
    155     }
    156 };
    157 /*
    158     线段/直线
    159 */
    160 struct line
    161 {
    162     point a,b;
    163     line(){}
    164     line(point _a,point _b)
    165     {
    166         a=_a;
    167         b=_b;
    168     }
    169     //判断线段相等
    170     bool operator==(line v)
    171     {
    172         return (a==v.a)&&(b==v.b);
    173     }
    174     //点p做倾斜角为angle的射线
    175     line(point p,double angle)
    176     {
    177         a=p;
    178         if (dblcmp(angle-pi/2)==0)
    179         {
    180             b=a.add(point(0,1));
    181         }
    182         else
    183         {
    184             b=a.add(point(1,tan(angle)));
    185         }
    186     }
    187     //直线一般式ax+by+c=0
    188     line(double _a,double _b,double _c)
    189     {
    190         if (dblcmp(_a)==0)
    191         {
    192             a=point(0,-_c/_b);
    193             b=point(1,-_c/_b);
    194         }
    195         else if (dblcmp(_b)==0)
    196         {
    197             a=point(-_c/_a,0);
    198             b=point(-_c/_a,1);
    199         }
    200         else
    201         {
    202             a=point(0,-_c/_b);
    203             b=point(1,(-_c-_a)/_b);
    204         }
    205     }
    206     //读入一个线段
    207     void input()
    208     {
    209         a.input();
    210         b.input();
    211     }
    212     //校准线段两点
    213     void adjust()
    214     {
    215         if (b<a)swap(a,b);
    216     }
    217     //线段长度
    218     double length()
    219     {
    220         return a.distance(b);
    221     }
    222     //直线倾斜角 0<=angle<180
    223     double angle()
    224     {
    225         double k=atan2(b.y-a.y,b.x-a.x);
    226         if (dblcmp(k)<0)k+=pi;
    227         if (dblcmp(k-pi)==0)k-=pi;
    228         return k;
    229     }
    230     //点和线段关系
    231     //1 在逆时针
    232     //2 在顺时针
    233     //3 平行
    234     int relation(point p)
    235     {
    236         int c=dblcmp(p.sub(a).det(b.sub(a)));
    237         if (c<0)return 1;
    238         if (c>0)return 2;
    239         return 3;
    240     }
    241     //点是否在线段上
    242     bool pointonseg(point p)
    243     {
    244         return dblcmp(p.sub(a).det(b.sub(a)))==0&&dblcmp(p.sub(a).dot(p.sub(b)))<=0;
    245     }
    246     //两线是否平行
    247     bool parallel(line v)
    248     {
    249         return dblcmp(b.sub(a).det(v.b.sub(v.a)))==0;
    250     }
    251     //线段和线段关系
    252     //0 不相交
    253     //1 非规范相交
    254     //2 规范相交
    255     int segcrossseg(line v)
    256     {
    257         int d1=dblcmp(b.sub(a).det(v.a.sub(a)));
    258         int d2=dblcmp(b.sub(a).det(v.b.sub(a)));
    259         int d3=dblcmp(v.b.sub(v.a).det(a.sub(v.a)));
    260         int d4=dblcmp(v.b.sub(v.a).det(b.sub(v.a)));
    261         if ((d1^d2)==-2&&(d3^d4)==-2)return 2;
    262         return (d1==0&&dblcmp(v.a.sub(a).dot(v.a.sub(b)))<=0||
    263                 d2==0&&dblcmp(v.b.sub(a).dot(v.b.sub(b)))<=0||
    264                 d3==0&&dblcmp(a.sub(v.a).dot(a.sub(v.b)))<=0||
    265                 d4==0&&dblcmp(b.sub(v.a).dot(b.sub(v.b)))<=0);
    266     }
    267     //线段和直线v关系
    268     int linecrossseg(line v)//*this seg v line
    269     {
    270         int d1=dblcmp(b.sub(a).det(v.a.sub(a)));
    271         int d2=dblcmp(b.sub(a).det(v.b.sub(a)));
    272         if ((d1^d2)==-2)return 2;
    273         return (d1==0||d2==0);
    274     }
    275     //直线和直线关系
    276     //0 平行
    277     //1 重合
    278     //2 相交
    279     int linecrossline(line v)
    280     {
    281         if ((*this).parallel(v))
    282         {
    283             return v.relation(a)==3;
    284         }
    285         return 2;
    286     }
    287     //求两线交点
    288     point crosspoint(line v)
    289     {
    290         double a1=v.b.sub(v.a).det(a.sub(v.a));
    291         double a2=v.b.sub(v.a).det(b.sub(v.a));
    292         return point((a.x*a2-b.x*a1)/(a2-a1),(a.y*a2-b.y*a1)/(a2-a1));
    293     }
    294     //点p到直线的距离
    295     double dispointtoline(point p)
    296     {
    297         return fabs(p.sub(a).det(b.sub(a)))/length();
    298     }
    299     //点p到线段的距离
    300     double dispointtoseg(point p)
    301     {
    302         if (dblcmp(p.sub(b).dot(a.sub(b)))<0||dblcmp(p.sub(a).dot(b.sub(a)))<0)
    303         {
    304             return min(p.distance(a),p.distance(b));
    305         }
    306         return dispointtoline(p);
    307     }
    308     //XXXXXXXX
    309     point lineprog(point p)
    310     {
    311         return a.add(b.sub(a).mul(b.sub(a).dot(p.sub(a))/b.sub(a).len2()));
    312     }
    313     //点p关于直线的对称点
    314     point symmetrypoint(point p)
    315     {
    316         point q=lineprog(p);
    317         return point(2*q.x-p.x,2*q.y-p.y);
    318     }
    319 };
    320 
    321 /*
    322     多边形
    323 */
    324 struct polygon
    325 {
    326     int n;//点个数
    327     point p[maxp];//顶点
    328     line l[maxp];//329     //读入一个多边形
    330     void input()
    331     {
    332         for (int i=0;i<n;i++)
    333         {
    334             p[i].input();
    335         }
    336     }
    337     //添加一个点
    338     void add(point q)
    339     {
    340         p[n++]=q;
    341     }
    342     //取得边
    343     void getline()
    344     {
    345         for (int i=0;i<n;i++)
    346         {
    347             l[i]=line(p[i],p[(i+1)%n]);
    348         }
    349     }
    350     struct cmp
    351     {
    352         point p;
    353         cmp(const point &p0){p=p0;}
    354         bool operator()(const point &aa,const point &bb)
    355         {
    356             point a=aa,b=bb;
    357             int d=dblcmp(a.sub(p).det(b.sub(p)));
    358             if (d==0)
    359             {
    360                 return dblcmp(a.distance(p)-b.distance(p))<0;
    361             }
    362             return d>0;
    363         }
    364     };
    365     void norm()
    366     {
    367         point mi=p[0];
    368         for (int i=1;i<n;i++)mi=min(mi,p[i]);
    369         sort(p,p+n,cmp(mi));
    370     }
    371     //求凸包存入多边形convex
    372     void getconvex(polygon &convex)
    373     {
    374         int i,j,k;
    375         sort(p,p+n);
    376         convex.n=n;
    377         for (i=0;i<min(n,2);i++)
    378         {
    379             convex.p[i]=p[i];
    380         }
    381         if (n<=2)return;
    382         int &top=convex.n;
    383         top=1;
    384         for (i=2;i<n;i++)
    385         {
    386             while (top&&convex.p[top].sub(p[i]).det(convex.p[top-1].sub(p[i]))<=0)
    387                 top--;
    388             convex.p[++top]=p[i];
    389         }
    390         int temp=top;
    391         convex.p[++top]=p[n-2];
    392         for (i=n-3;i>=0;i--)
    393         {
    394             while (top!=temp&&convex.p[top].sub(p[i]).det(convex.p[top-1].sub(p[i]))<=0)
    395                 top--;
    396             convex.p[++top]=p[i];
    397         }
    398     }
    399     //判断是否凸多边形
    400     bool isconvex()
    401     {
    402         bool s[3];
    403         memset(s,0,sizeof(s));
    404         int i,j,k;
    405         for (i=0;i<n;i++)
    406         {
    407             j=(i+1)%n;
    408             k=(j+1)%n;
    409             s[dblcmp(p[j].sub(p[i]).det(p[k].sub(p[i])))+1]=1;
    410             if (s[0]&&s[2])return 0;
    411         }
    412         return 1;
    413     }
    414     //点与多边形关系
    415     //0 外部
    416     //1 内部
    417     //2 边上
    418     //3 点上
    419     int relationpoint(point q)
    420     {
    421         int i,j;
    422         for (i=0;i<n;i++)
    423         {
    424             if (p[i]==q)return 3;
    425         }
    426         getline();
    427         for (i=0;i<n;i++)
    428         {
    429             if (l[i].pointonseg(q))return 2;
    430         }
    431         int cnt=0;
    432         for (i=0;i<n;i++)
    433         {
    434             j=(i+1)%n;
    435             int k=dblcmp(q.sub(p[j]).det(p[i].sub(p[j])));
    436             int u=dblcmp(p[i].y-q.y);
    437             int v=dblcmp(p[j].y-q.y);
    438             if (k>0&&u<0&&v>=0)cnt++;
    439             if (k<0&&v<0&&u>=0)cnt--;
    440         }
    441         return cnt!=0;
    442     }
    443     //线段与多边形关系
    444     //0 无任何交点
    445     //1 在多边形内长度为正
    446     //2 相交或与边平行
    447     int relationline(line u)
    448     {
    449         int i,j,k=0;
    450         getline();
    451         for (i=0;i<n;i++)
    452         {
    453             if (l[i].segcrossseg(u)==2)return 1;
    454             if (l[i].segcrossseg(u)==1)k=1;
    455         }
    456         if (!k)return 0;
    457         vector<point>vp;
    458         for (i=0;i<n;i++)
    459         {
    460             if (l[i].segcrossseg(u))
    461             {
    462                 if (l[i].parallel(u))
    463                 {
    464                     vp.pb(u.a);
    465                     vp.pb(u.b);
    466                     vp.pb(l[i].a);
    467                     vp.pb(l[i].b);
    468                     continue;
    469                 }
    470                 vp.pb(l[i].crosspoint(u));
    471             }
    472         }
    473         sort(vp.begin(),vp.end());
    474         int sz=vp.size();
    475         for (i=0;i<sz-1;i++)
    476         {
    477             point mid=vp[i].add(vp[i+1]).div(2);
    478             if (relationpoint(mid)==1)return 1;
    479         }
    480         return 2;
    481     }
    482     //直线u切割凸多边形左侧
    483     //注意直线方向
    484     void convexcut(line u,polygon &po)
    485     {
    486         int i,j,k;
    487         int &top=po.n;
    488         top=0;
    489         for (i=0;i<n;i++)
    490         {
    491             int d1=dblcmp(p[i].sub(u.a).det(u.b.sub(u.a)));
    492             int d2=dblcmp(p[(i+1)%n].sub(u.a).det(u.b.sub(u.a)));
    493             if (d1>=0)po.p[top++]=p[i];
    494             if (d1*d2<0)po.p[top++]=u.crosspoint(line(p[i],p[(i+1)%n]));
    495         }
    496     }
    497     //取得周长
    498     double getcircumference()
    499     {
    500         double sum=0;
    501         int i;
    502         for (i=0;i<n;i++)
    503         {
    504             sum+=p[i].distance(p[(i+1)%n]);
    505         }
    506         return sum;
    507     }
    508     //取得面积
    509     double getarea()
    510     {
    511         double sum=0;
    512         int i;
    513         for (i=0;i<n;i++)
    514         {
    515             sum+=p[i].det(p[(i+1)%n]);
    516         }
    517         return fabs(sum)/2;
    518     }
    519     bool getdir()//1代表逆时针 0代表顺时针
    520     {
    521         double sum=0;
    522         int i;
    523         for (i=0;i<n;i++)
    524         {
    525             sum+=p[i].det(p[(i+1)%n]);
    526         }
    527         if (dblcmp(sum)>0)return 1;
    528         return 0;
    529     }
    530     //取得重心
    531     point getbarycentre()
    532     {
    533         point ret(0,0);
    534         double area=0;
    535         int i;
    536         for (i=1;i<n-1;i++)
    537         {
    538             double tmp=p[i].sub(p[0]).det(p[i+1].sub(p[0]));
    539             if (dblcmp(tmp)==0)continue;
    540             area+=tmp;
    541             ret.x+=(p[0].x+p[i].x+p[i+1].x)/3*tmp;
    542             ret.y+=(p[0].y+p[i].y+p[i+1].y)/3*tmp;
    543         }
    544         if (dblcmp(area))ret=ret.div(area);
    545         return ret;
    546     }
    547     //点在凸多边形内部的判定
    548     int pointinpolygon(point q)
    549     {
    550         if (getdir())reverse(p,p+n);
    551         if (dblcmp(q.sub(p[0]).det(p[n-1].sub(p[0])))==0)
    552         {
    553             if (line(p[n-1],p[0]).pointonseg(q))return n-1;
    554             return -1;
    555         }
    556         int low=1,high=n-2,mid;
    557         while (low<=high)
    558         {
    559             mid=(low+high)>>1;
    560             if (dblcmp(q.sub(p[0]).det(p[mid].sub(p[0])))>=0&&dblcmp(q.sub(p[0]).det(p[mid+1].sub(p[0])))<0)
    561             {
    562                 polygon c;
    563                 c.p[0]=p[mid];
    564                 c.p[1]=p[mid+1];
    565                 c.p[2]=p[0];
    566                 c.n=3;
    567                 if (c.relationpoint(q))return mid;
    568                 return -1;
    569             }
    570             if (dblcmp(q.sub(p[0]).det(p[mid].sub(p[0])))>0)
    571             {
    572                 low=mid+1;
    573             }
    574             else
    575             {
    576                 high=mid-1;
    577             }
    578         }
    579         return -1;
    580     }
    581 };
    582 
    583 struct polygon P[100],R[100];       //P:continent    R:convex of the continent
    584 struct point key[100];              //key point
    585 int T,C,N,M;
    586 
    587 
    588 int main()
    589 {
    590     freopen("in.txt","r",stdin);
    591 
    592     cin>>T;
    593     while (T--)
    594     {
    595         cin>>C>>N;
    596         for (int i=1;i<=N;i++)
    597             key[i].input();
    598         for (int i=1;i<=C;i++)
    599         {
    600             cin>>M;
    601             P[i].n=M;
    602             P[i].input();
    603             P[i].getline();
    604             for (int j=1;j<=N;j++)
    605             {
    606                 if (P[i].relationpoint(key[j])==0)  //outside
    607                     key[j].dis=0;
    608                 else
    609                     key[j].dis=1;
    610             }
    611         }
    612         double mmx=0,dist;
    613         struct line maxLN;
    614         for (int i=1;i<N;i++)
    615         {
    616             struct line LN;
    617             LN.a=key[i];    LN.b=key[i+1];
    618             int tn=0;
    619             double tp[100];
    620             for (int j=1;j<=C;j++)      //continent j
    621             {
    622                 for (int k=0;k<P[j].n;k++)  //line k in continent j
    623                 {
    624                     line TL=P[j].l[k];
    625                     if (LN.segcrossseg(TL)!=0)
    626                     {
    627                         point tm=LN.crosspoint(TL); //crosspoint of continent && flight route
    628                         tp[tn]=key[i].distance(tm);
    629                         tn++;
    630                     }
    631                 }
    632             }
    633             for (int ii=0;ii<tn;ii++)  printf("%.6f ",tp[ii]);  printf("
    ");
    634             sort(tp,tp+tn,cmp);
    635             for (int ii=0;ii<tn;ii++)  printf("%.6f ",tp[ii]);  printf("
    ");
    636             if (key[i].dis==0)  //outside
    637             {
    638                 for (int j=0;j<tn;j=j+2)
    639                 {
    640                     double TM;
    641                     if (j==0)   TM=tp[j];   else TM=tp[j]-tp[j-1];
    642                     if (TM>mmx) 
    643                     {
    644                         maxLN=LN;
    645                         mmx=TM;
    646                         if (j==0) dist=mmx/2; else dist=tp[j-1]+mmx/2;
    647                     }
    648                 }
    649             }
    650             else    //inside
    651             {
    652                 for (int j=1;j<tn;j=j+2)
    653                 {
    654                     double TM;
    655                     TM=tp[j]-tp[j-1];
    656                     if (TM>mmx) 
    657                     {
    658                         maxLN=LN;
    659                         mmx=TM;
    660                         dist=tp[j-1]+mmx/2;
    661                     }
    662                 }
    663             }
    664         }
    665         double dx=maxLN.a.distance(maxLN.b);    dx=dist/dx;
    666         point A=maxLN.a,B=maxLN.b;
    667         point Ans=(A.x+(B.x-A.x)*dx,A.y+(B.y-A.y)*dy);
    668         
    669                 
    670         printf("%.6f
    ",mmx/2);
    671     }
    672     return 0;
    673 }
    View Code

    果然计算几何就是坑坑坑坑T^T

    在 http://poj.org/showcontest?contest_id=1477上面找的,实际上这一套题除了A剩下的都是坑= =

  • 相关阅读:
    css
    css加号波浪号
    C++对象池
    C++11 智能指针
    C++内存泄漏检测(调试工具)
    JSONP是个嘛玩意?解决跨域问题?
    使用django + KindEditor 开发个人博客系统
    前端文本框插件KindEditor
    jQuery AJAX
    Django ModelForm表单验证
  • 原文地址:https://www.cnblogs.com/pdev/p/4243660.html
Copyright © 2011-2022 走看看