精华内容
下载资源
问答
  • 半平面

    2017-09-08 10:37:00
    先写一下对半平面交的理解(之前学计算几何的时候,看了一眼半平面交,没学,然后在一次训练赛里就出了一道半平面交+数学期望的题,看来出来混迟早是要还的),目前大家用的好像都是zzy的半平面交模板,已经放弃的...

    先写一下对半平面交的理解(之前学计算几何的时候,看了一眼半平面交,没学,然后在一次训练赛里就出了一道半平面交+数学期望的题,看来出来混迟早是要还的),目前大家用的好像都是zzy的半平面交模板,已经放弃的之前的扫描线法了,用犄角的方法,再加上双端队列,可以达到nlogn的时间复杂度。

    半平面交说的通俗点就是求一些直线在一个二维平面内(暂时未二维平面,可以自行扩展)所构成的封闭图形,或者开放图形,或者线段,点,所构成的集合。有点类似于中学的线性规划,(但我印象中线性规划在acm里使用另外一种方法来处理的,半平面交只是相当于他的几何表示,但也不尽相同,线性规划的最优解一般是在顶点处,跑题了23333)。而多边形的内核则是在这个多边形内可以看到多边形的每一条边的点集,他的计算方法与半平面交类似。

    (下次在给出代码以及例题)

    -------------------------------手动分割---------------------------------------------------

     

    见kuangbin半平面交模板

    转载于:https://www.cnblogs.com/lalalatianlalu/p/7493374.html

    展开全文
  • 前后左右各个侧面的外部投影图——立面图;对建筑物各个侧面进行...假想用一个水平剖切平面沿建筑物窗口(比窗台稍高)的地方切开,移去上部分,然后向下进行投影所得到的投影图,称为建筑平面图,简称平面图。...

    http://www.qinxue.com/88.html

    http://www.xsteach.com/course/2855

    前后左右各个侧面的外部投影图——立面图;
    对建筑物各个侧面进行投影所得到的投影图,称为建筑立面图,简称立面图。

    水平剖切的投影图——平面图;
    假想用一个水平剖切平面沿建筑物窗口(比窗台稍高)的地方切开,移去上半部分,然后向下进行投影所得到的投影图,称为建筑平面图,简称平面图。

    竖直剖切的投影图——剖面图。
    假想用一个(或多个)垂直的剖切平面将房屋切开(应沿门窗洞口处),移出一部分,对剩下部分进行投影所得到的投影图,称为建筑剖面图,简称剖面图。

    展开全文
  • 半平面交学习笔记

    2019-08-22 20:59:18
    半平面:一条直线把一个平面分成的两个平面,如,直线ABABAB把平面分成左(上)半平面和右(下)半平面的两个平面。 那我们如何判断是在哪一个平面呢?有两种判定方法: 对于直线ABABAB,我们可以通过AAA、BBB...

    半平面交学习笔记

    半平面

    半平面:一条直线把一个平面分成的两个平面,如图,直线ABAB把平面分成左(上)半平面和右(下)半平面的两个平面。

    半平面1

    那我们如何判断是在哪一个平面呢?有两种判定方法:

    1. 对于直线ABAB,我们可以通过AABB的坐标算出其解析式,不妨设为ax+by+c=0ax+by+c=0,那么当CC在左平面时,将CC的坐标代入直线ABAB的解析式,其值大于0,即a×Cx+b×Cy+c>0a\times C_x+b\times C_y+c>0;当DD在右平面时,将DD的坐标也代入直线ABAB的解析式,其值小于0,即a×Dx+b×Dy+c<0a\times D_x+b\times D_y+c<0

    2. (前置知识:矢量的叉乘,可见我的矢量&凸包学习笔记)对于直线ABAB顺次的两个端点AABB,如果cross(BA,CA)>0cross(B-A,C-A)>0(这里的相减操作定义为AB=(AxBx,AyBy)A-B=(A_x-B_x,A_y-B_y),所以BAB-A就是BBAA为原点的坐标,CAC-A就是CCAA为原点的坐标),那么根据右手法则,CC在左(上)半平面;如果cross(BA,DA)<0cross(B-A,D-A)<0,那么根据右手法则,DD在右(下)半平面。

    半平面交

    半平面交,顾名思义,就是许多半平面的交集,一般我们指的是左半平面。

    我们先举道例题:

    P4196 [CQOI2006]凸多边形

    做法:首先我们注意到,某个多边形的每条边所在直线的半平面交就是这个多边形:

    半平面交1

    那么我们可以把题目给出的所有凸多边形变成对应边数的直线,然后求这些直线的半平面交。

    半平面交怎么求?

    首先,对于每一个凸多边形,按时针将每一条边建成直线。

    然后对于每一条直线,以起点为原点,求出它们各自的极角,并将它们按极角排序。

    排序完后,如果有两条直线极角相同,那么我们肯定只留最左侧的直线,我们就要去重。

    然后将第1122条直线放入双端队列dequedequedequedeque里存的是当前半平面交的边,因为半平面交是一个凸多边形

    然后每一次加入直线到dequedeque之前:

    1. 计算队尾的两条直线(也就是最陡的两条)的交点,如果它在要加入的直线的右边,那么就弹出队尾。

    2. 计算队首的两条直线(也就是最缓的两条)的交点,如果它在要加入的直线的右边,那么就弹出队首。

    然后将新直线加入队尾。

    加入完所有直线后:

    1. 计算队尾的两条直线(也就是最陡的两条)的交点,如果它在队首的直线的右边,那么就弹出队尾。

    2. 计算队首的两条直线(也就是最缓的两条)的交点,如果它在队尾的直线的右边,那么就弹出队首。

    然后算出每两条直线的交点,这就是半平面交——一个凸多边形的顶点。

    最后直接算出其面积就好了。(算面积方法详见我的矢量&凸包学习笔记

    最后代码如下:

    #include<bits/stdc++.h>
    
    #define eps 1e-6
    #define N 510
    
    using namespace std;
    
    struct Point
    {
        double x,y;
        Point(){};
        Point(double a,double b)
        {
            x=a,y=b;
        }
    }p[N],e[N];
    
    struct Line
    {
        Point s,t;
        double d;
        Line(){};
        Line(Point a,Point b)
        {
            s=a,t=b;
        }
    }l[N],q[N];
    
    Point operator + (Point a,Point b)
    {
        return Point{a.x+b.x,a.y+b.y};
    }
    
    Point operator - (Point a,Point b)
    {
        return Point{a.x-b.x,a.y-b.y};
    }
    
    Point operator * (Point a,double x)
    {
        return Point{a.x*x,a.y*x};
    }
    
    int n,cnt,cnt1;
    double ans;
    
    double cross(Point a,Point b)
    {
        return a.x*b.y-b.x*a.y;
    }
    
    double dis(Point a,Point b)
    {
        return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    }
    
    int compare(double x,double y)
    {
        if(fabs(x-y)<eps)return 0;
        return x-y<0?-1:1;
    }
    
    bool cmp(Line a,Line b)
    {
        if(!compare(a.d,b.d))return cross(a.t-a.s,b.t-a.s)>0;
        return a.d<b.d;
    }
    
    bool onright(Point a,Line l)
    {
        return compare(cross(l.t-l.s,a-l.s),0)>0?0:1;
    }
    
    Point intersection(Line a,Line b)
    {
        Point u=a.s-b.s;
        Point v=a.t-a.s;
        Point w=b.t-b.s;
        double t=cross(w,u)/cross(v,w);
        return a.s+v*t;
    }
    
    double angle(Point a)
    {
        return atan2(a.y,a.x);
    }
    
    void half()
    {
        sort(l+1,l+cnt+1,cmp);
        cnt1=0;
        for(int i=1;i<cnt;i++)
        {
            if(!compare(l[i+1].d-l[i].d,0))continue;
            l[++cnt1]=l[i];
        }
        l[++cnt1]=l[cnt];
        cnt=cnt1;
        int L=1,R=0;
        q[++R]=l[1],q[++R]=l[2];
        for(int i=3;i<=cnt;i++)
        {
            while(L<R&&onright(intersection(q[R],q[R-1]),l[i]))R--;
            while(L<R&&onright(intersection(q[L],q[L+1]),l[i]))L++;
            q[++R]=l[i];
        }
        while(L<R&&onright(intersection(q[R],q[R-1]),q[L]))R--;
        while(L<R&&onright(intersection(q[L],q[L+1]),q[R]))L++;
        q[++R]=q[L];
        cnt1=0;
        for(int i=L;i<R;i++)e[++cnt1]=intersection(q[i],q[i+1]);
        e[++cnt1]=e[1];
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            int m;
            scanf("%d",&m);
            Point last,st;
            for(int j=1;j<=m;j++)
            {
                double x,y;
                scanf("%lf%lf",&x,&y);
                if(j==1)
                {
                    last=st=Point{x,y};
                    continue;
                }
                l[++cnt]=Line{last,Point{x,y}};
                last=Point{x,y};
            }
            l[++cnt]=Line{last,st};
        }
        for(int i=1;i<=cnt;i++)l[i].d=angle(l[i].s-l[i].t);
        half();
        if(cnt1<3)
        {
            puts("0.000");
            return 0;
        }
        for(int i=1;i<cnt1;i++)ans+=cross(e[i],e[i+1]);
        printf("%.3lf\n",ans/2.0);
        return 0;
    }
    

    练习

    poj3130 How I Mathematician Wonder What You Are!/poj3335 Rotating Scoreboard/poj1474 Video Surveillance 判断半平面交是否是平面而不是一条线、一个点或没有。看最后交点数是否大于2不就好了……

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    
    #define eps 1e-6
    #define N 510
    
    using namespace std;
    
    struct Point
    {
        double x,y;
        Point(){};
        Point(double a,double b)
        {
            x=a,y=b;
        }
    }p[N],e[N];
    
    struct Line
    {
        Point s,t;
        double d;
        Line(){};
        Line(Point a,Point b)
        {
            s=a,t=b;
        }
    }l[N],q[N];
    
    Point operator + (Point a,Point b)
    {
        return Point(a.x+b.x,a.y+b.y);
    }
    
    Point operator - (Point a,Point b)
    {
        return Point(a.x-b.x,a.y-b.y);
    }
    
    Point operator * (Point a,double x)
    {
        return Point(a.x*x,a.y*x);
    }
    
    int n,cnt,cnt1;
    double ans;
    
    double cross(Point a,Point b)
    {
        return a.x*b.y-b.x*a.y;
    }
    
    double dis(Point a,Point b)
    {
        return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    }
    
    int compare(double x,double y)
    {
        if(fabs(x-y)<eps)return 0;
        return x-y<0?-1:1;
    }
    
    bool cmp(Line a,Line b)
    {
        if(!compare(a.d,b.d))return cross(a.t-a.s,b.t-a.s)>0;
        return a.d<b.d;
    }
    
    bool onright(Point a,Line l)
    {
        return compare(cross(l.t-l.s,a-l.s),0)>0?0:1;
    }
    
    Point intersection(Line a,Line b)
    {
        Point u=a.s-b.s;
        Point v=a.t-a.s;
        Point w=b.t-b.s;
        double t=cross(w,u)/cross(v,w);
        return a.s+v*t;
    }
    
    double angle(Point a)
    {
        return atan2(a.y,a.x);
    }
    
    void half()
    {
        sort(l+1,l+cnt+1,cmp);
        cnt1=0;
        for(int i=1;i<cnt;i++)
        {
            if(!compare(l[i+1].d-l[i].d,0))continue;
            l[++cnt1]=l[i];
        }
        l[++cnt1]=l[cnt];
        cnt=cnt1;
        int L=1,R=0;
        q[++R]=l[1],q[++R]=l[2];
        for(int i=3;i<=cnt;i++)
        {
            while(L<R&&onright(intersection(q[R],q[R-1]),l[i]))R--;
            while(L<R&&onright(intersection(q[L],q[L+1]),l[i]))L++;
            q[++R]=l[i];
        }
        while(L<R&&onright(intersection(q[R],q[R-1]),q[L]))R--;
        while(L<R&&onright(intersection(q[L],q[L+1]),q[R]))L++;
        q[++R]=q[L];
        cnt1=0;
        for(int i=L;i<R;i++)e[++cnt1]=intersection(q[i],q[i+1]);
        e[++cnt1]=e[1];
    }
    
    int main()
    {
    	while(~scanf("%d",&n)&&n)
    	{
    		cnt=0;
    		Point last,st;
    	    for(int i=1;i<=n;i++)
    	    {
    	        double x,y;
    	        scanf("%lf%lf",&x,&y);
    	        if(i==1)
    	        {
    	        	last=st=Point(x,y);
    	        	continue;
    	        }
    	        l[++cnt]=Line(last,Point(x,y));
    	        last=Point(x,y);
    	    }
    	    l[++cnt]=Line(last,st);
    	    for(int i=1;i<=cnt;i++)l[i].d=angle(l[i].s-l[i].t);
    	    half();
    	    ans=0;
    	    if(cnt1<3)ans=0;
    	    else for(int i=1;i<cnt1;i++)ans+=cross(e[i],e[i+1]);
    	    if(!ans)puts("0");
    	    else puts("1");
    	}
        return 0;
    }
    

    poj1279 Art Gallery 模板……代码不放了。

    poj3384 Feng Shui 将凸多边形的每条边内移rr,那么圆心就在这些直线的半平面交的端点上,最后暴力枚举或旋转卡壳即可。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    
    #define eps 1e-6
    #define N 110
    #define INF 0x7fffffff
    
    using namespace std;
    
    struct Point
    {
        double x,y;
        Point(){};
        Point(double a,double b)
        {
            x=a,y=b;
        }
    }e[N],p[N],p1,p2;
    
    Point operator + (Point a,Point b)
    {
        return Point(a.x+b.x,a.y+b.y);
    }
    
    Point operator - (Point a,Point b)
    {
        return Point(a.x-b.x,a.y-b.y);
    }
    
    Point operator * (Point a,double x)
    {
        return Point(a.x*x,a.y*x);
    }
    
    double angle(Point a)
    {
        return atan2(a.y,a.x);
    }
    
    struct Line
    {
        Point s,t;
        double d;
        Line(){};
        Line(Point a,Point b)
        {
            s=a,t=b,d=angle(b-a);
        }
    }l[N],q[N];
    
    int n,cnt,cnt1;
    double r,ans=-INF;
    
    double cross(Point a,Point b)
    {
        return a.x*b.y-b.x*a.y;
    }
    
    double dis(Point a,Point b)
    {
        return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    }
    
    int compare(double x,double y)
    {
        if(fabs(x-y)<eps)return 0;
        return x-y<0?-1:1;
    }
    
    bool cmp(Line a,Line b)
    {
        if(!compare(a.d,b.d))return compare(cross(a.t-a.s,b.t-a.s),0)>0;
        return a.d<b.d;
    }
    
    bool onright(Point a,Line l)
    {
        return compare(cross(l.t-l.s,a-l.s),0)>=0?0:1;
    }
    
    Point intersection(Line a,Line b)
    {
        Point u=a.s-b.s;
        Point v=a.t-a.s;
        Point w=b.t-b.s;
        double t=cross(w,u)/cross(v,w);
        return a.s+v*t;
    }
    
    void half()
    {
        sort(l+1,l+cnt+1,cmp);
        cnt1=0;
        for(int i=1;i<cnt;i++)
        {
            if(!compare(l[i+1].d-l[i].d,0))continue;
            l[++cnt1]=l[i];
        }
        l[++cnt1]=l[cnt];
        cnt=cnt1;
        int L=1,R=0;
        q[++R]=l[1],q[++R]=l[2];
        for(int i=3;i<=cnt;i++)
        {
            while(L<R&&onright(intersection(q[R],q[R-1]),l[i]))R--;
            while(L<R&&onright(intersection(q[L],q[L+1]),l[i]))L++;
            q[++R]=l[i];
        }
        while(L<R&&onright(intersection(q[R],q[R-1]),q[L]))R--;
        while(L<R&&onright(intersection(q[L],q[L+1]),q[R]))L++;
        q[++R]=q[L];
        cnt1=0;
        for(int i=L;i<R;i++)e[++cnt1]=intersection(q[i],q[i+1]);
    }
    
    int main()
    {
        scanf("%d%lf",&n,&r);
        for(int i=1;i<=n;i++)scanf("%lf%lf",&p[i].x,&p[i].y);
        p[0]=p[n];
        for(int i=n;i>=1;i--)
        {
            double k=r/dis(p[i-1],p[i]);
            double x1=k*(p[i-1].y-p[i].y);
            double y1=k*(p[i].x-p[i-1].x);
            l[++cnt]=Line(Point(p[i].x-x1,p[i].y-y1),Point(p[i-1].x-x1,p[i-1].y-y1));
        }
        half();
        for(int i=1;i<=cnt1;i++)
        {
            for(int j=i;j<=cnt1;j++)
            {
                double d=dis(e[i],e[j]);
                if(d>ans)
                {
                    ans=d;
                    p1=e[i];
                    p2=e[j];
                }
            }
        }
        printf("%.4lf %.4lf %.4lf %.4lf\n",p1.x,p1.y,p2.x,p2.y);
        return 0;
    }
    
    展开全文
  • POJ3525 半平面

    2015-02-05 20:47:00
    首先介绍半平面半平面交的概念: 半平面:对于一条有向直线,它的方向的左手侧就是它所划定的半平面范围。如所示: 半平面交:多个半平面的交集。有点类似二元函数的线性规划。如半平面交:用的...

    题意:求某凸多边形内部离边界最远的点到边界的距离

     

    首先介绍半平面、半平面交的概念:

    半平面:对于一条有向直线,它的方向的左手侧就是它所划定的半平面范围。如图所示:

     

    半平面交:多个半平面的交集。有点类似二元函数的线性规划。如图

     

    求半平面交:用的kuangbin模板= =

     

     

    sol:二分答案

      二分距离值,按这个值把边界向内缩,再求新的半平面交。如图:

    绿色的是原图形,蓝色是按距离值向里面缩进去之后得到的新图形。对这个新图做半平面交即可。

    若半平面交存在,说明与边界的距离是该值的点存在(半平面交里面的点都是)

     

    那么如何把图形向里面缩呢?其实在纸上画画就容易多了:

    因为半平面是一条有向直线,所以只要有直线上的任意一点和方向就可以了,这个点在不在对应的那条边上都无所谓。

    如图,棕色是一开始的边,黑色是它对应的半平面。

    设当前二分答案值是mid,对这条边做一个长度为mid的法向量(图中绿色)

    棕色边起点+法向量即得到新半平面上的一个点(图中蓝色)

    新半平面的方向和原来一样,直接平移过来就行了。

     

    在做法向量的时候采用向量的概念能简化问题。这里在kuangbin模板的基础上加上了向量类Vector:

     1 struct Vector:public point
     2 {
     3     Vector(){}
     4     Vector(double a,double b)
     5     {
     6         x=a;    y=b;
     7     }
     8     Vector(point _a,point _b)   //a->b
     9     {
    10         double dx=_b.x-_a.x;
    11         double dy=_b.y-_a.y;
    12         x=dx;   y=dy;
    13     }
    14     Vector(line v)
    15     {
    16         double dx=v.b.x-v.a.x;
    17         double dy=v.b.y-v.a.y;
    18         x=dx;   y=dy;
    19     }
    20     double length()
    21     {
    22         return (sqrt(x*x+y*y));
    23     }
    24     Vector Normal()      //返回this的单位长度的法向量
    25     {
    26         double L=sqrt(x*x+y*y);
    27         Vector Vans=Vector(-y/L,x/L);
    28         return Vans;
    29     }
    30 };
    31     

    重载了三种构造函数:给出向量的坐标值(x,y)、给出向量首尾两点、用一条线段作为向量

     

    ----------------------------------------------

    AC Code:

      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-6;
     32 const double pi=acos(-1.0);
     33 const double inf=1e20;
     34 const int maxp=1111;
     35 int dblcmp(double d)
     36 {
     37     if (fabs(d)<eps)return 0;
     38     return d>eps?1:-1;
     39 }
     40 inline double sqr(double x){return x*x;}
     41 struct point
     42 {
     43     double x,y;
     44     point(){}
     45     point(double _x,double _y):
     46     x(_x),y(_y){};
     47     void input()
     48     {
     49         scanf("%lf%lf",&x,&y);
     50     }
     51     void output()
     52     {
     53         printf("%.2f %.2f\n",x,y);
     54     }
     55     bool operator==(point a)const
     56     {
     57         return dblcmp(a.x-x)==0&&dblcmp(a.y-y)==0;
     58     }
     59     bool operator<(point a)const
     60     {
     61         return dblcmp(a.x-x)==0?dblcmp(y-a.y)<0:x<a.x;
     62     }
     63     double len()
     64     {
     65         return hypot(x,y);
     66     }
     67     double len2()
     68     {
     69         return x*x+y*y;
     70     }
     71     double distance(point p)
     72     {
     73         return hypot(x-p.x,y-p.y);
     74     }
     75     point add(point p)
     76     {
     77         return point(x+p.x,y+p.y);
     78     }
     79     point sub(point p)
     80     {
     81         return point(x-p.x,y-p.y);
     82     }
     83     point mul(double b)
     84     {
     85         return point(x*b,y*b);
     86     }
     87     point div(double b)
     88     {
     89         return point(x/b,y/b);
     90     }
     91     double dot(point p)
     92     {
     93         return x*p.x+y*p.y;
     94     }
     95     double det(point p)
     96     {
     97         return x*p.y-y*p.x;
     98     }
     99     double rad(point a,point b)
    100     {
    101         point p=*this;
    102         return fabs(atan2(fabs(a.sub(p).det(b.sub(p))),a.sub(p).dot(b.sub(p))));
    103     }
    104     point trunc(double r)
    105     {
    106         double l=len();
    107         if (!dblcmp(l))return *this;
    108         r/=l;
    109         return point(x*r,y*r);
    110     }
    111     point rotleft()
    112     {
    113         return point(-y,x);
    114     }
    115     point rotright()
    116     {
    117         return point(y,-x);
    118     }
    119     point rotate(point p,double angle)//绕点p逆时针旋转angle角度
    120     {
    121         point v=this->sub(p);
    122         double c=cos(angle),s=sin(angle);
    123         return point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c);
    124     }
    125 };
    126 struct line
    127 {
    128     point a,b;
    129     line(){}
    130     line(point _a,point _b)
    131     {
    132         a=_a;
    133         b=_b;
    134     }
    135     bool operator==(line v)
    136     {
    137         return (a==v.a)&&(b==v.b);
    138     }
    139     //倾斜角angle
    140     line(point p,double angle)
    141     {
    142         a=p;
    143         if (dblcmp(angle-pi/2)==0)
    144         {
    145             b=a.add(point(0,1));
    146         }
    147         else
    148         {
    149             b=a.add(point(1,tan(angle)));
    150         }
    151     }
    152     //ax+by+c=0
    153     line(double _a,double _b,double _c)
    154     {
    155         if (dblcmp(_a)==0)
    156         {
    157             a=point(0,-_c/_b);
    158             b=point(1,-_c/_b);
    159         }
    160         else if (dblcmp(_b)==0)
    161         {
    162             a=point(-_c/_a,0);
    163             b=point(-_c/_a,1);
    164         }
    165         else
    166         {
    167             a=point(0,-_c/_b);
    168             b=point(1,(-_c-_a)/_b);
    169         }
    170     }
    171     void input()
    172     {
    173         a.input();
    174         b.input();
    175     }
    176     void adjust()
    177     {
    178         if (b<a)swap(a,b);
    179     }
    180     double length()
    181     {
    182         return a.distance(b);
    183     }
    184     double angle()//直线倾斜角 0<=angle<180
    185     {
    186         double k=atan2(b.y-a.y,b.x-a.x);
    187         if (dblcmp(k)<0)k+=pi;
    188         if (dblcmp(k-pi)==0)k-=pi;
    189         return k;
    190     }
    191     //点和线段关系
    192     //1 在逆时针
    193     //2 在顺时针
    194     //3 平行
    195     int relation(point p)
    196     {
    197         int c=dblcmp(p.sub(a).det(b.sub(a)));
    198         if (c<0)return 1;
    199         if (c>0)return 2;
    200         return 3;
    201     }
    202     bool pointonseg(point p)
    203     {
    204         return dblcmp(p.sub(a).det(b.sub(a)))==0&&dblcmp(p.sub(a).dot(p.sub(b)))<=0;
    205     }
    206     bool parallel(line v)
    207     {
    208         return dblcmp(b.sub(a).det(v.b.sub(v.a)))==0;
    209     }
    210     //2 规范相交
    211     //1 非规范相交
    212     //0 不相交
    213     int segcrossseg(line v)
    214     {
    215         int d1=dblcmp(b.sub(a).det(v.a.sub(a)));
    216         int d2=dblcmp(b.sub(a).det(v.b.sub(a)));
    217         int d3=dblcmp(v.b.sub(v.a).det(a.sub(v.a)));
    218         int d4=dblcmp(v.b.sub(v.a).det(b.sub(v.a)));
    219         if ((d1^d2)==-2&&(d3^d4)==-2)return 2;
    220         return (d1==0&&dblcmp(v.a.sub(a).dot(v.a.sub(b)))<=0||
    221                 d2==0&&dblcmp(v.b.sub(a).dot(v.b.sub(b)))<=0||
    222                 d3==0&&dblcmp(a.sub(v.a).dot(a.sub(v.b)))<=0||
    223                 d4==0&&dblcmp(b.sub(v.a).dot(b.sub(v.b)))<=0);
    224     }
    225     int linecrossseg(line v)//*this seg v line
    226     {
    227         int d1=dblcmp(b.sub(a).det(v.a.sub(a)));
    228         int d2=dblcmp(b.sub(a).det(v.b.sub(a)));
    229         if ((d1^d2)==-2)return 2;
    230         return (d1==0||d2==0);
    231     }
    232     //0 平行
    233     //1 重合
    234     //2 相交
    235     int linecrossline(line v)
    236     {
    237         if ((*this).parallel(v))
    238         {
    239             return v.relation(a)==3;
    240         }
    241         return 2;
    242     }
    243     point crosspoint(line v)
    244     {
    245         double a1=v.b.sub(v.a).det(a.sub(v.a));
    246         double a2=v.b.sub(v.a).det(b.sub(v.a));
    247         return point((a.x*a2-b.x*a1)/(a2-a1),(a.y*a2-b.y*a1)/(a2-a1));
    248     }
    249     double dispointtoline(point p)
    250     {
    251         return fabs(p.sub(a).det(b.sub(a)))/length();
    252     }
    253     double dispointtoseg(point p)
    254     {
    255         if (dblcmp(p.sub(b).dot(a.sub(b)))<0||dblcmp(p.sub(a).dot(b.sub(a)))<0)
    256         {
    257             return min(p.distance(a),p.distance(b));
    258         }
    259         return dispointtoline(p);
    260     }
    261     point lineprog(point p)
    262     {
    263         return a.add(b.sub(a).mul(b.sub(a).dot(p.sub(a))/b.sub(a).len2()));
    264     }
    265     point symmetrypoint(point p)
    266     {
    267         point q=lineprog(p);
    268         return point(2*q.x-p.x,2*q.y-p.y);
    269     }
    270 };
    271 
    272 struct Vector:public point
    273 {
    274     Vector(){}
    275     Vector(double a,double b)
    276     {
    277         x=a;    y=b;
    278     }
    279     Vector(point _a,point _b)   //a->b
    280     {
    281         double dx=_b.x-_a.x;
    282         double dy=_b.y-_a.y;
    283         x=dx;   y=dy;
    284     }
    285     Vector(line v)
    286     {
    287         double dx=v.b.x-v.a.x;
    288         double dy=v.b.y-v.a.y;
    289         x=dx;   y=dy;
    290     }
    291     double length()
    292     {
    293         return (sqrt(x*x+y*y));
    294     }
    295     Vector Normal()
    296     {
    297         double L=sqrt(x*x+y*y);
    298         Vector Vans=Vector(-y/L,x/L);
    299         return Vans;
    300     }
    301 };
    302 
    303 struct halfplane:public line    //半平面
    304 {
    305     double angle;
    306     halfplane(){}
    307     //表示向量 a->b逆时针(左侧)的半平面
    308     halfplane(point _a,point _b)
    309     {
    310         a=_a;
    311         b=_b;
    312     }
    313     halfplane(line v)
    314     {
    315         a=v.a;
    316         b=v.b;
    317     }
    318     void calcangle()
    319     {
    320         angle=atan2(b.y-a.y,b.x-a.x);
    321     }
    322     bool operator<(const halfplane &b)const
    323     {
    324         return angle<b.angle;
    325     }
    326 };
    327 struct halfplanes   //半平面交
    328 {
    329     int n;
    330     halfplane hp[maxp];
    331     point p[maxp];
    332     int que[maxp];
    333     int st,ed;
    334     void push(halfplane tmp)
    335     {
    336         hp[n++]=tmp;
    337     }
    338     void unique()
    339     {
    340         int m=1,i;
    341         for (i=1;i<n;i++)
    342         {
    343             if (dblcmp(hp[i].angle-hp[i-1].angle))hp[m++]=hp[i];
    344             else if (dblcmp(hp[m-1].b.sub(hp[m-1].a).det(hp[i].a.sub(hp[m-1].a))>0))hp[m-1]=hp[i];
    345         }
    346         n=m;
    347     }
    348     bool halfplaneinsert()
    349     {
    350         int i;
    351         for (i=0;i<n;i++)hp[i].calcangle();
    352         sort(hp,hp+n);
    353         unique();
    354         que[st=0]=0;
    355         que[ed=1]=1;
    356         p[1]=hp[0].crosspoint(hp[1]);
    357         for (i=2;i<n;i++)
    358         {
    359             while (st<ed&&dblcmp((hp[i].b.sub(hp[i].a).det(p[ed].sub(hp[i].a))))<0)ed--;
    360             while (st<ed&&dblcmp((hp[i].b.sub(hp[i].a).det(p[st+1].sub(hp[i].a))))<0)st++;
    361             que[++ed]=i;
    362             if (hp[i].parallel(hp[que[ed-1]]))return false;
    363             p[ed]=hp[i].crosspoint(hp[que[ed-1]]);
    364         }
    365         while (st<ed&&dblcmp(hp[que[st]].b.sub(hp[que[st]].a).det(p[ed].sub(hp[que[st]].a)))<0)ed--;
    366         while (st<ed&&dblcmp(hp[que[ed]].b.sub(hp[que[ed]].a).det(p[st+1].sub(hp[que[ed]].a)))<0)st++;
    367         if (st+1>=ed)return false;
    368         return true;
    369     }
    370     /*
    371     void getconvex(polygon &con)
    372     {
    373         p[st]=hp[que[st]].crosspoint(hp[que[ed]]);
    374         con.n=ed-st+1;
    375         int j=st,i=0;
    376         for (;j<=ed;i++,j++)
    377         {
    378             con.p[i]=p[j];
    379         }
    380     }*/
    381 };
    382 
    383 point p[1000];
    384 Vector V[1000],Vt[1000];
    385 halfplanes TH;
    386 int n;
    387 
    388 int main()
    389 {
    390     //freopen("in.txt","r",stdin);
    391 
    392     while (cin>>n)
    393     {
    394         if (n==0)   break;
    395         for (int i=0;i<n;i++)   //n points:[0..n-1]
    396             p[i].input();
    397 
    398         for (int i=0;i<n;i++)   //v[i]:p[i]->p[i+1]
    399         {
    400             V[i]=Vector(p[i],p[(i+1)%n]);
    401             //printf("vector:   %.6lf  %.6lf\n",V[i].x,V[i].y);
    402             Vt[i]=V[i].Normal();
    403         }
    404 
    405         double l=0,r=5001;
    406         while (r-l>eps)
    407         {
    408             double mid=(l+r)/2;
    409             //double mid=l+(r-l)/2;
    410             TH.n=0;
    411             //halfplanes TH;
    412 
    413             for (int i=0;i<n;i++)
    414             {
    415                 point t1=p[i].add(Vt[i].mul(mid));
    416                 point t2=t1.add(V[i]);
    417 
    418                 line tmp=line(t1,t2);
    419                 TH.push(halfplane(tmp));
    420             }
    421 
    422             //printf("%.6lf  %d",mid,TH.n);
    423 
    424             if (TH.halfplaneinsert())
    425             {
    426                 //cout<<"OK"<<endl;
    427                 l=mid;      //l=mid+0.00001;
    428             }
    429             else
    430             {
    431                 //cout<<"NO"<<endl;
    432                 r=mid;      //r=mid-0.00001;
    433             }
    434         }
    435         printf("%.6lf\n",l);
    436     }
    437     return 0;
    438 }
    View Code

     

     

    推荐iPad上一个免费又好用的绘图板:Sketches

     

    转载于:https://www.cnblogs.com/pdev/p/4275911.html

    展开全文
  • 【详解】半平面交算法入门详解(计算几何)

    万次阅读 多人点赞 2018-10-30 16:28:28
    半平面交 简介 博客背景 笔者在学习半平面交时,网上找入门博客资源甚少,且大部分难以理解,故在稍稍入门了半平面交后,写此博客,希望能对大家有所帮助。若有错误,麻烦指出。 半平面交是什么? 我们知道一条直线...
  • 半平面交模板

    2016-02-18 16:49:00
    半平面交的结果:1.凸多边形(后面会讲解到)2.无界,因为有可能若干半平面没有形成封闭3.直线,线段,点,空(属于特殊情况吧) 算法:1:根据上可以知道,运用给出的多边形每相邻两点形成一条直线来切割原有...
  • 定义 半平面:平面上的直线及其一侧的部分,可以用Ax+By+c≥0Ax+By+c≥0Ax+...举个例子,定义有向直线的右边为半平面,那么半平面交就是下的红色区域。 求解 可以发现半平面交是一个凸多边形(当然也有是一个...
  • 半平面交算法及简单应用 半平面:一条直线把二维平面分成两个平面。 半平面交:在二维几何平面上,给出若干个半平面,求它们的公共部分 半平面交的结果:1.凸多边形(后面会讲解到)2.无界,因为有可能若干...
  • bzoj 2618 半平面

    2019-04-16 21:05:38
    觉得巨恶心不知道怎么办,结果一看题解发现因为凸多边形相交还是一个多边形,并不会变成多个奇怪的很多个小图形,所以可以直接半平面交求面积,测板子+1,过样例就A真爽。 #include<bits/stdc++.h> #define ...
  • poj2451 半平面

    千次阅读 2012-07-29 01:26:51
    题意:在(0,10000)*(0,10000)的...每个半平面由两点(x1,y1)(x2,y2)确定的直线确定,规定半平面为直线的左边,即存在一点(x,y) 使得(x – x1) * (y – y2) – (x – x2) * (y – y1) = (x1 – x)
  • 自己在学习半平面交的时候看到网上有几张图片很不错就 down 下来在本文中使用了……如果博主大大不乐意请联系我删除。下面给出两个我觉得不错的博客: 1.半平面交讲解1 2.半平面交讲解2 定义: 半平面:...
  • 半平面交定义 首先要了解半平面交是什么,简单来讲,就是一堆直线,我们只取他的一边,所构成的区域就是半平面交。比如,有4条有向直线,我们都只取直线左边的那一部分,所有直线左边平面的交集就是半平面交。如下...
  • bzoj3190 赛车 半平面

    2016-03-02 18:09:53
    对于一辆赛车,速度vi,位置ki,转化为一次函数yi=vix+... 然后就相当于n个半平面半平面交了。。。  注意在x轴左侧的直线需要去掉。  然后过了所有原题数据。。但是bzoj上狂WA不止T_T为什么新加的数据这么强。。。
  • 考虑轮廓的每一条边,要看到这条边就必须在这条边以上的一个半平面内,因此求半平面交即可,样例: 不妨将半平面交与地面上的直线看成分段函数,分别为f(x)与g(x),则所求即为h(x) = f(x) - g(x)的最小值,由于f...
  • 题意:给出一个以n个点为轮廓...只我们发现只有这个点在每个直线所在半平面以上的时候才能看到,如样例:还注意到,只有在原的端点或半平面交的端点处才会更新答案。#include #include #include #include using name
  • 题意:求出几个封闭图形围成的内部区域面积。...把每一条边作为有向直线,逆时针遍历全,左侧的半平面交 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring>...
  • 题目大意:给出一个村庄的轮廓,在这个村庄里可以在随意的地方建一个瞭望塔。这个塔须要足够高,使得可以看得村庄的全貌。求这个瞭望塔的最小高度。 思路:对于村庄中的每...全部边的半平面交区域就是上面的...
  • hdu 3761 半平面

    2019-09-24 00:23:42
    表示当只需要删除一个点时的状况,其中红色的区域建立了司令部,不论删除任何的一个点,都不可能找到司令部,因此最大的要删除的点大于1,所以通过二分需要删除的最大值即可。 1 /* 2 题意:给出n个点...
  • 题目大意及模拟退火题解:见... 这次用半平面交写了一遍……求出半平面交之后。枚举原半平面交的每一个点,求出答案就可以 #include<cmath> #include<cstdio> #include<cstring> #include<...
  • matplotlib之平面图

    2019-07-09 13:25:00
    一、对数坐标系   import matplotlib.pyplot as mp y = [1, 10, 100, 1000, 100, 10, 1] mp.figure('Semilogy', facecolor='lightgray') mp.subplot(211) ax = mp.gca() ax.xaxis.set_major_...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 517
精华内容 206
关键字:

半平面图