zoukankan      html  css  js  c++  java
  • Most Distant Point from the Sea

    Most Distant Point from the Sea

    http://poj.org/problem?id=3525

    Time Limit: 5000MS   Memory Limit: 65536K
    Total Submissions: 6214   Accepted: 2745   Special Judge

    Description

    The main land of Japan called Honshu is an island surrounded by the sea. In such an island, it is natural to ask a question: “Where is the most distant point from the sea?” The answer to this question for Honshu was found in 1996. The most distant point is located in former Usuda Town, Nagano Prefecture, whose distance from the sea is 114.86 km.

    In this problem, you are asked to write a program which, given a map of an island, finds the most distant point from the sea in the island, and reports its distance from the sea. In order to simplify the problem, we only consider maps representable by convex polygons.

    Input

    The input consists of multiple datasets. Each dataset represents a map of an island, which is a convex polygon. The format of a dataset is as follows.

    n    
    x1   y1
       
    xn   yn

    Every input item in a dataset is a non-negative integer. Two input items in a line are separated by a space.

    n in the first line is the number of vertices of the polygon, satisfying 3 ≤ n ≤ 100. Subsequent n lines are the x- and y-coordinates of the n vertices. Line segments (xiyi)–(xi+1yi+1) (1 ≤ i ≤ n − 1) and the line segment (xnyn)–(x1y1) form the border of the polygon in counterclockwise order. That is, these line segments see the inside of the polygon in the left of their directions. All coordinate values are between 0 and 10000, inclusive.

    You can assume that the polygon is simple, that is, its border never crosses or touches itself. As stated above, the given polygon is always a convex one.

    The last dataset is followed by a line containing a single zero.

    Output

    For each dataset in the input, one line containing the distance of the most distant point from the sea should be output. An output line should not contain extra characters such as spaces. The answer should not have an error greater than 0.00001 (10−5). You may output any number of digits after the decimal point, provided that the above accuracy condition is satisfied.

    Sample Input

    4
    0 0
    10000 0
    10000 10000
    0 10000
    3
    0 0
    10000 0
    7000 1000
    6
    0 40
    100 20
    250 40
    250 70
    100 90
    0 70
    3
    0 0
    10000 10000
    5000 5001
    0

    Sample Output

    5000.000000
    494.233641
    34.542948
    0.353553

    求在多边形中画一个圆的最大半径。

    反过来想,看多边形最多可以往内减少多少距离,该距离就是圆的半径,二分判断即可

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<vector>
      5 #include<cmath>
      6 #include<algorithm>
      7 using namespace std;
      8 const double eps=1e-8;
      9 const double INF=1e20;
     10 const double PI=acos(-1.0);
     11 
     12 int sgn(double x){
     13     if(fabs(x)<eps) return 0;
     14     if(x<0) return -1;
     15     else return 1;
     16 }
     17 
     18 inline double sqr(double x){return x*x;}
     19 inline double hypot(double a,double b){return sqrt(a*a+b*b);}
     20 struct Point{
     21     double x,y;
     22     Point(){}
     23     Point(double _x,double _y){
     24         x=_x;
     25         y=_y;
     26     }
     27     void input(){
     28         scanf("%lf %lf",&x,&y);
     29     }
     30     void output(){
     31         printf("%.2f %.2f
    ",x,y);
     32     }
     33     bool operator == (const Point &b)const{
     34         return sgn(x-b.x) == 0 && sgn(y-b.y)== 0;
     35     }
     36     bool operator < (const Point &b)const{
     37         return sgn(x-b.x)==0?sgn(y-b.y)<0:x<b.x;
     38     }
     39     Point operator - (const Point &b)const{
     40         return Point(x-b.x,y-b.y);
     41     }
     42     //叉积
     43     double operator ^ (const Point &b)const{
     44         return x*b.y-y*b.x;
     45     }
     46     //点积
     47     double operator * (const Point &b)const{
     48         return x*b.x+y*b.y;
     49     }
     50     //返回长度
     51     double len(){
     52         return hypot(x,y);
     53     }
     54     //返回长度的平方
     55     double len2(){
     56         return x*x+y*y;
     57     }
     58     //返回两点的距离
     59     double distance(Point p){
     60         return hypot(x-p.x,y-p.y);
     61     }
     62     Point operator + (const Point &b)const{
     63         return Point(x+b.x,y+b.y);
     64     }
     65     Point operator * (const double &k)const{
     66         return Point(x*k,y*k);
     67     }
     68     Point operator / (const double &k)const{
     69         return Point(x/k,y/k);
     70     }
     71 
     72     //计算pa和pb的夹角
     73     //就是求这个点看a,b所成的夹角
     74     ///LightOJ1202
     75     double rad(Point a,Point b){
     76         Point p=*this;
     77         return fabs(atan2(fabs((a-p)^(b-p)),(a-p)*(b-p)));
     78     }
     79     //化为长度为r的向量
     80     Point trunc(double r){
     81         double l=len();
     82         if(!sgn(l)) return *this;
     83         r/=l;
     84         return Point(x*r,y*r);
     85     }
     86     //逆时针转90度
     87     Point rotleft(){
     88         return Point(-y,x);
     89     }
     90     //顺时针转90度
     91     Point rotright(){
     92         return Point(y,-x);
     93     }
     94     //绕着p点逆时针旋转angle
     95     Point rotate(Point p,double angle){
     96         Point v=(*this) -p;
     97         double c=cos(angle),s=sin(angle);
     98         return Point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c);
     99     }
    100 };
    101 
    102 struct Line{
    103     Point s,e;
    104     Line(){}
    105     Line(Point _s,Point _e){
    106         s=_s;
    107         e=_e;
    108     }
    109     bool operator==(Line v){
    110         return (s==v.s)&&(e==v.e);
    111     }
    112     //根据一个点和倾斜角angle确定直线,0<=angle<pi
    113     Line(Point p,double angle){
    114         s=p;
    115         if(sgn(angle-PI/2)==0){
    116             e=(s+Point(0,1));
    117         }
    118         else{
    119             e=(s+Point(1,tan(angle)));
    120         }
    121     }
    122     //ax+by+c=0;
    123     Line(double a,double b,double c){
    124         if(sgn(a)==0){
    125             s=Point(0,-c/b);
    126             e=Point(1,-c/b);
    127         }
    128         else if(sgn(b)==0){
    129             s=Point(-c/a,0);
    130             e=Point(-c/a,1);
    131         }
    132         else{
    133             s=Point(0,-c/b);
    134             e=Point(1,(-c-a)/b);
    135         }
    136     }
    137     void input(){
    138         s.input();
    139         e.input();
    140     }
    141     void adjust(){
    142         if(e<s) swap(s,e);
    143     }
    144     //求线段长度
    145     double length(){
    146         return s.distance(e);
    147     }
    148     //返回直线倾斜角 0<=angle<pi
    149     double angle(){
    150         double k=atan2(e.y-s.y,e.x-s.x);
    151         if(sgn(k)<0) k+=PI;
    152         if(sgn(k-PI)==0) k-=PI;
    153         return k;
    154     }
    155     //点和直线的关系
    156     //1 在左侧
    157     //2 在右侧
    158     //3 在直线上
    159     int relation(Point p){
    160         int c=sgn((p-s)^(e-s));
    161         if(c<0) return 1;
    162         else if(c>0) return 2;
    163         else return 3;
    164     }
    165     //点在线段上的判断
    166     bool pointonseg(Point p){
    167         return sgn((p-s)^(e-s))==0&&sgn((p-s)*(p-e))<=0;
    168     }
    169     //两向量平行(对应直线平行或重合)
    170     bool parallel(Line v){
    171         return sgn((e-s)^(v.e-v.s))==0;
    172     }
    173     //两线段相交判断
    174     //2 规范相交
    175     //1 非规范相交
    176     //0 不相交
    177     int segcrossseg(Line v){
    178         int d1=sgn((e-s)^(v.s-s));
    179         int d2=sgn((e-s)^(v.e-s));
    180         int d3=sgn((v.e-v.s)^(s-v.s));
    181         int d4=sgn((v.e-v.s)^(e-v.s));
    182         if((d1^d2)==-2&&(d3^d4)==-2) return 2;
    183         return (d1==0&&sgn((v.s-s)*(v.s-e))<=0||
    184                 d2==0&&sgn((v.e-s)*(v.e-e))<=0||
    185                 d3==0&&sgn((s-v.s)*(s-v.e))<=0||
    186                 d4==0&&sgn((e-v.s)*(e-v.e))<=0);
    187     }
    188     //直线和线段相交判断
    189     //-*this line -v seg
    190     //2 规范相交
    191     //1 非规范相交
    192     //0 不相交
    193     int linecrossseg(Line v){
    194         int d1=sgn((e-s)^(v.s-s));
    195         int d2=sgn((e-s)^(v.e-s));
    196         if((d1^d2)==-2) return 2;
    197         return (d1==0||d2==0);
    198     }
    199     //两直线关系
    200     //0 平行
    201     //1 重合
    202     //2 相交
    203     int linecrossline(Line v){
    204         if((*this).parallel(v))
    205             return v.relation(s)==3;
    206         return 2;
    207     }
    208     //求两直线的交点
    209     //要保证两直线不平行或重合
    210     Point crosspoint(Line v){
    211         double a1=(v.e-v.s)^(s-v.s);
    212         double a2=(v.e-v.s)^(e-v.s);
    213         return Point((s.x*a2-e.x*a1)/(a2-a1),(s.y*a2-e.y*a1)/(a2-a1));
    214     }
    215     //点到直线的距离
    216     double dispointtoline(Point p){
    217         return fabs((p-s)^(e-s))/length();
    218     }
    219     //点到线段的距离
    220     double dispointtoseg(Point p){
    221         if(sgn((p-s)*(e-s))<0||sgn((p-e)*(s-e))<0)
    222             return min(p.distance(s),p.distance(e));
    223         return dispointtoline(p);
    224     }
    225     //返回线段到线段的距离
    226     //前提是两线段不相交,相交距离就是0了
    227     double dissegtoseg(Line v){
    228         return min(min(dispointtoseg(v.s),dispointtoseg(v.e)),min(v.dispointtoseg(s),v.dispointtoseg(e)));
    229     }
    230     //返回点P在直线上的投影
    231     Point lineprog(Point p){
    232         return s+(((e-s)*((e-s)*(p-s)))/((e-s).len2()));
    233     }
    234     //返回点P关于直线的对称点
    235     Point symmetrypoint(Point p){
    236         Point q=lineprog(p);
    237         return Point(2*q.x-p.x,2*q.y-p.y);
    238     }
    239 };
    240 
    241 struct circle{
    242     Point p;
    243     double r;
    244     circle(){}
    245     circle(Point _p,double _r){
    246         p=_p;
    247         r=_r;
    248     }
    249 
    250     circle(double x,double y,double _r){
    251         p=Point(x,y);
    252         r=_r;
    253     }
    254 
    255     circle(Point a,Point b,Point c){///三角形的外接圆
    256         Line u=Line((a+b)/2,((a+b)/2)+((b-a).rotleft()));
    257         Line v=Line((b+c)/2,((b+c)/2)+((c-b).rotleft()));
    258         p=u.crosspoint(v);
    259         r=p.distance(a);
    260     }
    261 
    262     circle(Point a,Point b,Point c,bool t){///三角形的内切圆
    263         Line u,v;
    264         double m=atan2(b.y-a.y,b.x-a.x),n=atan2(c.y-a.y,c.x-a.x);
    265         u.s=a;
    266         u.e=u.s+Point(cos((n+m)/2),sin((n+m)/2));
    267         v.s=b;
    268         m=atan2(a.y-b.y,a.x-b.x),n=atan2(c.y-b.y,c.x-b.x);
    269         v.e=v.s+Point(cos((n+m)/2),sin((n+m)/2));
    270         p=u.crosspoint(v);
    271         r=Line(a,b).dispointtoseg(p);
    272     }
    273 
    274     void input(){
    275         p.input();
    276         scanf("%lf",&r);
    277     }
    278 
    279     void output(){
    280         printf("%.2f %.2f %.2f
    ",p.x,p.y,r);
    281     }
    282 
    283     bool operator==(circle v){
    284         return (p==v.p)&&sgn(r-v.r)==0;
    285     }
    286 
    287     bool operator<(circle v)const{
    288         return ((p<v.p)||((p==v.p)&&sgn(r-v.r)<0));
    289     }
    290 
    291     double area(){
    292         return PI*r*r;
    293     }
    294 
    295     double circumference(){ ///周长
    296         return 2*PI*r;
    297     }
    298 
    299     int relation(Point b){///点和圆的关系  0圆外  1圆上  2圆内
    300         double dst=b.distance(p);
    301         if(sgn(dst-r)<0) return 2;
    302         else if(sgn(dst-r)==0) return 1;
    303         return 0;
    304     }
    305 
    306     int relationseg(Line v){///线段和圆的关系,比较的是圆心到线段的距离和半径的关系
    307         double dst=v.dispointtoseg(p);
    308         if(sgn(dst-r)<0) return 2;
    309         else if(sgn(dst-r)==0) return 1;
    310         return 0;
    311     }
    312 
    313     int relationline(Line v){///直线和圆的关系,比较的是圆心到直线的距离和半径的关系
    314         double dst=v.dispointtoline(p);
    315         if(sgn(dst-r)<0) return 2;
    316         else if(sgn(dst-r)==0) return 1;
    317         return 0;
    318     }
    319 
    320     int relationcircle(circle v){///两圆的关系  5相离 4外切 3相交 2内切 1内含
    321         double d=p.distance(v.p);
    322         if(sgn(d-r-v.r)>0) return 5;
    323         if(sgn(d-r-v.r)==0) return 4;
    324         double l=fabs(r-v.r);
    325         if(sgn(d-r-v.r)<0&&sgn(d-l)>0) return 3;
    326         if(sgn(d-l)==0) return 2;
    327         if(sgn(d-l)<0)  return 1;
    328     }
    329 
    330     int pointcrosscircle(circle v,Point &p1,Point &p2){///求两个圆的交点,0没有交点 1一个交点 2两个交点
    331         int rel=relationcircle(v);
    332         if(rel == 1 || rel == 5) return 0;
    333         double d=p.distance(v.p);
    334         double l=(d*d+r*r-v.r*v.r)/2*d;
    335         double h=sqrt(r*r-l*l);
    336         Point tmp=p+(v.p-p).trunc(l);
    337         p1=tmp+((v.p-p).rotleft().trunc(h));
    338         p2=tmp+((v.p-p).rotright().trunc(h));
    339         if(rel == 2 || rel == 4) return 1;
    340         return 2;
    341     }
    342 
    343     int pointcrossline(Line v,Point &p1,Point &p2){///求直线和圆的交点,返回交点的个数
    344         if(!(*this).relationline(v)) return 0;
    345         Point a=v.lineprog(p);
    346         double d=v.dispointtoline(p);
    347         d=sqrt(r*r-d*d);
    348         if(sgn(d)==0) {
    349             p1=a;
    350             p2=a;
    351             return 1;
    352         }
    353         p1=a+(v.e-v.s).trunc(d);
    354         p2=a-(v.e-v.s).trunc(d);
    355         return 2;
    356     }
    357 
    358     int getcircle(Point a,Point b,double r1,circle &c1,circle &c2){///得到过a,b两点,半径为r1的两个圆
    359         circle x(a,r1),y(b,r1);
    360         int t=x.pointcrosscircle(y,c1.p,c2.p);
    361         if(!t) return 0;
    362         c1.r=c2.r=r;
    363         return t;
    364     }
    365 
    366     int getcircle(Line u,Point q,double r1,circle &c1,circle &c2){///得到与直线u相切,过点q,半径为r1的圆
    367         double dis = u.dispointtoline(q);
    368         if(sgn(dis-r1*2)>0) return 0;
    369         if(sgn(dis)==0) {
    370             c1.p=q+((u.e-u.s).rotleft().trunc(r1));
    371             c2.p=q+((u.e-u.s).rotright().trunc(r1));
    372             c1.r=c2.r=r1;
    373             return 2;
    374         }
    375         Line u1=Line((u.s+(u.e-u.s).rotleft().trunc(r1)),(u.e+(u.e-u.s).rotleft().trunc(r1)));
    376         Line u2=Line((u.s+(u.e-u.s).rotright().trunc(r1)),(u.e+(u.e-u.s).rotright().trunc(r1)));
    377         circle cc=circle(q,r1);
    378         Point p1,p2;
    379         if(!cc.pointcrossline(u1,p1,p2)) cc.pointcrossline(u2,p1,p2);
    380         c1=circle(p1,r1);
    381         if(p1==p2){
    382             c2=c1;
    383             return 1;
    384         }
    385         c2=circle(p2,r1);
    386         return 2;
    387     }
    388 
    389     int getcircle(Line u,Line v,double r1,circle &c1,circle &c2,circle &c3,circle &c4){///同时与直线u,v相切,半径为r1的圆
    390         if(u.parallel(v)) return 0;///两直线平行
    391         Line u1=Line(u.s+(u.e-u.s).rotleft().trunc(r1),u.e+(u.e-u.s).rotleft().trunc(r1));
    392         Line u2=Line(u.s+(u.e-u.s).rotright().trunc(r1),u.e+(u.e-u.s).rotright().trunc(r1));
    393         Line v1=Line(v.s+(v.e-v.s).rotleft().trunc(r1),v.e+(v.e-v.s).rotleft().trunc(r1));
    394         Line v2=Line(v.s+(v.e-v.s).rotright().trunc(r1),v.e+(v.e-v.s).rotright().trunc(r1));
    395         c1.r=c2.r=c3.r=c4.r=r1;
    396         c1.p=u1.crosspoint(v1);
    397         c2.p=u1.crosspoint(v2);
    398         c3.p=u2.crosspoint(v1);
    399         c4.p=u2.crosspoint(v2);
    400         return 4;
    401     }
    402 
    403     int getcircle(circle cx,circle cy,double r1,circle &c1,circle &c2){///同时与不相交圆 cx,cy相切,半径为r1的圆
    404         circle x(cx.p,r1+cx.r),y(cy.p,r1+cy.r);
    405         int t=x.pointcrosscircle(y,c1.p,c2.p);
    406         if(!t) return 0;
    407         c1.r=c2.r=r1;
    408         return t;
    409     }
    410 
    411     int tangentline(Point q,Line &u,Line &v){///过一点作圆的切线(先判断点和圆的关系)
    412         int x=relation(q);
    413         if(x==2) return 0;
    414         if(x==1){
    415             u=Line(q,q+(q-p).rotleft());
    416             v=u;
    417             return 1;
    418         }
    419         double d=p.distance(q);
    420         double l=r*r/d;
    421         double h=sqrt(r*r-l*l);
    422         u=Line(q,p+((q-p).trunc(l)+(q-p).rotleft().trunc(h)));
    423         v=Line(q,p+((q-p).trunc(l)+(q-p).rotright().trunc(h)));
    424         return 2;
    425     }
    426 
    427     double areacircle(circle v){///求两圆相交的面积
    428         int rel=relationcircle(v);
    429         if(rel >= 4) return 0.0;
    430         if(rel <= 2) return min(area(),v.area());
    431         double d=p.distance(v.p);
    432         double hf=(r+v.r+d)/2.0;
    433         double ss=2*sqrt(hf*(hf-r)*(hf-v.r)*(hf-d));
    434         double a1=acos((r*r+d*d-v.r*v.r)/(2.0*r*d));
    435         a1=a1*r*r;
    436         double a2=acos((v.r*v.r+d*d-r*r)/(2.0*v.r*d));
    437         a2=a2*v.r*v.r;
    438         return a1+a2-ss;
    439     }
    440 
    441     double areatriangle(Point a,Point b){///求圆和三角形pab的相交面积
    442         if(sgn((p-a)^(p-b))==0) return 0.0;
    443         Point q[5];
    444         int len=0;
    445         q[len++]=a;
    446         Line l(a,b);
    447         Point p1,p2;
    448         if(pointcrossline(l,q[1],q[2])==2){
    449             if(sgn((a-q[1])*(b-q[1]))<0) q[len++]=q[1];
    450             if(sgn((a-q[2])*(b-q[2]))<0) q[len++]=q[2];
    451         }
    452         q[len++]=b;
    453         if(len==4 && sgn((q[0]-q[1])*(q[2]-q[1]))>0) swap(q[1],q[2]);
    454         double res=0;
    455         for(int i=0;i<len-1;i++){
    456             if(relation(q[i])==0||relation(q[i+1])==0){
    457                 double arg=p.rad(q[i],q[i+1]);
    458                 res+=r*r*arg/2.0;
    459             }
    460             else{
    461                 res+=fabs((q[i]-p)^(q[i+1]-p))/2.0;
    462             }
    463         }
    464         return res;
    465     }
    466 };
    467 
    468 struct polygon{
    469     int n;
    470     Point p[100010];
    471     Line l[100010];
    472     void input(int _n){
    473         n=_n;
    474         for(int i=0;i<n;i++){
    475             p[i].input();
    476         }
    477     }
    478 
    479     void add(Point q){
    480         p[n++]=q;
    481     }
    482 
    483     void getline(){
    484         for(int i=0;i<n;i++){
    485             l[i]=Line(p[i],p[(i+1)%n]);
    486         }
    487     }
    488 
    489     struct cmp{
    490         Point p;
    491         cmp(const Point &p0){p=p0;}
    492         bool operator()(const Point &aa,const Point &bb){
    493             Point a=aa,b=bb;
    494             int d=sgn((a-p)^(b-p));
    495             if(d==0){
    496                 return sgn(a.distance(p)-b.distance(p))<0;
    497             }
    498             return d>0;
    499         }
    500     };
    501 
    502     void norm(){///进行极角排序
    503         Point mi=p[0];
    504         for(int i=1;i<n;i++){
    505             mi=min(mi,p[i]);
    506         }
    507         sort(p,p+n,cmp(mi));
    508     }
    509 
    510     void getconvex(polygon &convex){///得到第一种凸包的方法,编号为0~n-1,可能要特判所有点共点或共线的特殊情况
    511         sort(p,p+n);
    512         convex.n=n;
    513         for(int i=0;i<min(n,2);i++){
    514             convex.p[i]=p[i];
    515         }
    516         if(convex.n==2&&(convex.p[0]==convex.p[1])) convex.n--;
    517         if(n<=2) return;
    518         int &top=convex.n;
    519         top=1;
    520         for(int i=2;i<n;i++){
    521             while(top&&sgn((convex.p[top]-p[i])^(convex.p[top-1]-p[i]))<0) top--;
    522             convex.p[++top]=p[i];
    523         }
    524         int temp=top;
    525         convex.p[++top]=p[n-2];
    526         for(int i=n-3;i>=0;i--){
    527             while(top!=temp&&sgn((convex.p[top]-p[i])^(convex.p[top-1]-p[i]))<=0) top--;
    528             convex.p[++top]=p[i];
    529         }
    530         if(convex.n==2&&(convex.p[0]==convex.p[1])) convex.n--;
    531         convex.norm();
    532     }
    533 
    534     void Graham(polygon &convex){///得到凸包的第二种方法
    535         norm();
    536         int &top=convex.n;
    537         top=0;
    538         if(n==1){
    539             top=1;
    540             convex.p[0]=p[0];
    541             return;
    542         }
    543         if(n==2){
    544             top=2;
    545             convex.p[0]=p[0];
    546             convex.p[1]=p[1];
    547             if(convex.p[0]==convex.p[1]) top--;
    548             return;
    549         }
    550         convex.p[0]=p[0];
    551         convex.p[1]=p[1];
    552         top=2;
    553         for(int i=2;i<n;i++){
    554             while(top>1&&sgn((convex.p[top-1]-convex.p[top-2])^(p[i]-convex.p[top-2]))<=0) top--;
    555             convex.p[top++]=p[i];
    556         }
    557         if(convex.n==2 && (convex.p[0]==convex.p[1])) convex.n--;
    558     }
    559 
    560     bool inconvex(){///判断是不是凸的
    561         bool s[3];
    562         memset(s,false,sizeof(s));
    563         for(int i=0;i<n;i++){
    564             int j=(i+1)%n;
    565             int k=(j+1)%n;
    566             s[sgn((p[j]-p[i])^(p[k]-p[i]))+1]=true;
    567             if(s[0]&&s[2]) return false;
    568         }
    569         return true;
    570     }
    571 
    572     int relationpoint(Point q){///判断点和任意多边形的关系  3点上 2边上 1内部 0外部
    573         for(int i=0;i<n;i++){
    574             if(p[i]==q) return 3;
    575         }
    576         getline();
    577         for(int i=0;i<n;i++){
    578             if(l[i].pointonseg(q)) return 2;
    579         }
    580         int cnt=0;
    581         for(int i=0;i<n;i++){
    582             int j=(i+1)%n;
    583             int k=sgn((q-p[j])^(p[i]-p[j]));
    584             int u=sgn(p[i].y-q.y);
    585             int v=sgn(p[j].y-q.y);
    586             if(k>0&&u<0&&v>=0) cnt++;
    587             if(k<0&&v<0&&u>=0) cnt--;
    588         }
    589         return cnt!=0;
    590     }
    591 
    592     void convexcnt(Line u,polygon &po){///直线u切割凸多边形左侧  注意直线方向
    593         int &top=po.n;
    594         top=0;
    595         for(int i=0;i<n;i++){
    596             int d1=sgn((u.e-u.s)^(p[i]-u.s));
    597             int d2=sgn((u.e-u.s)^(p[(i+1)%n]-u.s));
    598             if(d1>=0) po.p[top++]=p[i];
    599             if(d1*d2<0)po.p[top++]=u.crosspoint(Line(p[i],p[(i+1)%n]));
    600         }
    601     }
    602 
    603     double getcircumference(){///得到周长
    604         double sum=0;
    605         for(int i=0;i<n;i++){
    606             sum+=p[i].distance(p[(i+1)%n]);
    607         }
    608         return sum;
    609     }
    610 
    611     double getarea(){///得到面积
    612         double sum=0;
    613         for(int i=0;i<n;i++){
    614             sum+=(p[i]^p[(i+1)%n]);
    615         }
    616         return fabs(sum)/2;
    617     }
    618 
    619     bool getdir(){///得到方向 1表示逆时针  0表示顺时针
    620         double sum=0;
    621         for(int i=0;i<n;i++){
    622             sum+=(p[i]^p[(i+1)%n]);
    623         }
    624         if(sgn(sum)>0) return 1;
    625         return 0;
    626     }
    627 
    628     Point getbarycentre(){///得到重心
    629         Point ret(0,0);
    630         double area=0;
    631         for(int i=1;i<n-1;i++){
    632             double tmp=(p[i]-p[0])^(p[i+1]-p[0]);
    633             if(sgn(tmp)==0) continue;
    634             area+=tmp;
    635             ret.x+=(p[0].x+p[i].x+p[i+1].x)/3*tmp;
    636             ret.y+=(p[0].y+p[i].y+p[i+1].y)/3*tmp;
    637         }
    638         if(sgn(area)) ret =ret/area;
    639         return ret;
    640     }
    641 
    642     double areacircle(circle c){///多边形和圆交的面积
    643         double ans=0;
    644         for(int i=0;i<n;i++){
    645             int j=(i+1)%n;
    646             if(sgn((p[j]-c.p)^(p[i]-c.p))>=0) ans+=c.areatriangle(p[i],p[j]);
    647             else ans-=c.areatriangle(p[i],p[j]);
    648         }
    649         return fabs(ans);
    650     }
    651 
    652     int relationcircle(circle c){///多边形和圆的关系 2圆完全在多边形内  1圆在多边形里面,碰到了多边形的边界  0其他
    653         getline();
    654         int x=2;
    655         if(relationpoint(c.p)!=1) return 0;
    656         for(int i=0;i<n;i++){
    657             if(c.relationseg(l[i])==2) return 0;
    658             if(c.relationseg(l[i])==1) x=1;
    659         }
    660         return x;
    661     }
    662 };
    663 
    664 struct halfplane:public Line{
    665     double angle;
    666     halfplane(){}
    667     halfplane(Point _s,Point _e){///表示向量s->e逆时针(左侧)的半平面
    668         s=_s;
    669         e=_e;
    670     }
    671     halfplane(Line v){
    672         s=v.s;
    673         e=v.e;
    674     }
    675     void calcangle(){
    676         angle=atan2(e.y-s.y,e.x-s.x);
    677     }
    678     bool operator<(const halfplane &b)const{
    679         return angle<b.angle;
    680     }
    681 };
    682 
    683 struct halfplanes{
    684     int n;
    685     halfplane hp[2020];
    686     Point p[2020];
    687     int que[2020];
    688     int st,ed;
    689     void push(halfplane tmp){
    690         hp[n++]=tmp;
    691     }
    692 
    693     void unique(){///去重
    694         int m=1;
    695         for(int i=1;i<n;i++){
    696             if(sgn(hp[i].angle-hp[i-1].angle)!=0) hp[m++]=hp[i];
    697             else if(sgn((hp[m-1].e-hp[m-1].s)^(hp[i].s-hp[m-1].s))>0) hp[m-1]=hp[i];
    698         }
    699         n=m;
    700     }
    701     bool halfplaneinsert(){
    702         for(int i=0;i<n;i++) hp[i].calcangle();
    703         sort(hp,hp+n);
    704         unique();
    705         que[st=0]=0;
    706         que[ed=1]=1;
    707         p[1]=hp[0].crosspoint(hp[1]);
    708         for(int i=2;i<n;i++){
    709             while(st<ed&&sgn((hp[i].e-hp[i].s)^(p[ed]-hp[i].s))<0) ed--;
    710             while(st<ed&&sgn((hp[i].e-hp[i].s)^(p[st+1]-hp[i].s))<0) st++;
    711             que[++ed]=i;
    712             if(hp[i].parallel(hp[que[ed-1]])) return false;
    713             p[ed]=hp[i].crosspoint(hp[que[ed-1]]);
    714         }
    715         while(st<ed&&sgn((hp[que[st]].e-hp[que[st]].s)^(p[ed]-hp[que[st]].s))<0) ed--;
    716         while(st<ed&&sgn((hp[que[ed]].e-hp[que[ed]].s)^(p[st+1]-hp[que[ed]].s))<0) st++;
    717         if(st+1>=ed) return false;
    718         return true;
    719     }
    720 
    721     void getconvex(polygon &con){///得到最后半平面交得到的凸多边形,要先调用halfplaneinsert()且返回true
    722         p[st]=hp[que[st]].crosspoint(hp[que[ed]]);
    723         con.n=ed-st+1;
    724         for(int j=st,i=0;j<=ed;i++,j++){
    725             con.p[i]=p[j];
    726         }
    727     }
    728 };
    729 
    730 bool Check(Line a,Line b){
    731     if(sgn((a.s-a.e)^(b.s-a.e))*sgn((a.s-a.e)^(b.e-a.e))>0) return false;
    732     if(sgn((b.s-b.e)^(a.s-b.e))*sgn((b.s-b.e)^(a.e-b.e))>0) return false;
    733     if(sgn(max(a.s.x,a.e.x)-min(b.s.x,b.e.x))>=0&&sgn(max(b.s.x,b.e.x)-min(a.s.x,a.e.x))>=0
    734      &&sgn(max(a.s.y,a.e.y)-min(b.s.y,b.e.y))>=0&&sgn(max(b.s.y,b.e.y)-min(a.s.y,a.e.y))>=0)
    735         return true;
    736     else return false;
    737 }
    738 
    739 halfplanes hps;
    740 int n;
    741 Point p[105];
    742 polygon poly;
    743 
    744 void change(Point a,Point b,Point &c,Point &d,double p)///将线段ab往左移动距离p
    745 {
    746     double len = a.distance(b);
    747     double dx = (a.y - b.y)*p/len;
    748     double dy = (b.x - a.x)*p/len;
    749     c.x = a.x + dx; c.y = a.y + dy;
    750     d.x = b.x + dx; d.y = b.y + dy;
    751 }
    752 
    753 int main(){
    754     int n;
    755     while(~scanf("%d",&n)){
    756         if(!n) break;
    757         for(int i=0;i<n;i++){
    758             p[i].input();
    759         }
    760         double L=0,R=5005,mid;
    761         Point aa,bb;
    762         while(R-L>eps){
    763             mid=(L+R)/2;
    764             hps.n=0;
    765             for(int i=0;i<n;i++){
    766                 change(p[i],p[(i+1)%n],aa,bb,mid);
    767                 hps.push(halfplane(aa,bb));
    768             }
    769             if(hps.halfplaneinsert()){
    770                 L=mid;
    771             }
    772             else{
    773                 R=mid;
    774             }
    775         }
    776         printf("%.6f
    ",L);
    777     }
    778     return 0;
    779 }
    View Code
  • 相关阅读:
    小学生入门激光SLAM<二>、2.1-前端点云帧间匹配
    小学生入门激光SLAM<一>、激光雷达去除畸变
    imgui开发笔记<1>、ubuntu环境下快速应用
    ROS问题记录
    LibTorch实战六:U2-Net理论详解<一>
    git-clone小技巧
    深度学习模型部署概述
    debian10 docker 安装 jenkins
    FastDFS集群部署
    python中的metaclass
  • 原文地址:https://www.cnblogs.com/Fighting-sh/p/10816474.html
Copyright © 2011-2022 走看看