半平面交 求多边形内核问题

 多边形的内核可以理解为:

在多边形找到一块区域,使这块区域中的任何一个点都能够和多边形上的任意一点相连而不受到多边形上其他边的阻挡

也可以抽象的理解为在这块区域中任意位置放一个旋转摄像头,这个摄像头可以监控多边形的整个区域

多边形内核是否存在可以利用半平面交的思想去求解

将多边形上的每一条边作为逆时针顺序的射线,在每一条线左侧的就是可行区域

譬如:

比如这个多边形

蓝色区域便是内核

这样利用半平面交的nlogn的算法就可以轻松判断

这里是三道这样类型的题目:poj 3335 , poj 1474 , poj 1279

poj 3335

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;
#define N 105
#define ll long long
#define eps 1e-9

int dcmp(double x)
{
    if(fabs(x)<eps) return 0;
    else return x<0?-1:1;
}

struct Point{
    double x,y;
    Point(double x=0 , double y=0):x(x),y(y){}
}p[N] , poly[N];

typedef Point Vector;

struct Line{
    Point p;
    Vector v;
    double ang;
    Line(){}
    Line(Point p , Vector v):p(p),v(v){ang = atan2(v.y , v.x);}
    bool operator<(const Line &m) const{
        return dcmp(ang-m.ang)<0;
    }
}line[N];

Vector operator+(Vector a , Vector b){return Vector(a.x+b.x , a.y+b.y);}
Vector operator-(Vector a , Vector b){return Vector(a.x-b.x , a.y-b.y);}
Vector operator*(Vector a , double b){return Vector(a.x*b , a.y*b);}
Vector operator/(Vector a , double b){return Vector(a.x/b , a.y/b);}

double Cross(Vector a , Vector b){return a.x*b.y-a.y*b.x;}

bool OnLeft(Line L , Point P)
{
    return dcmp(Cross(L.v , P-L.p))>=0;
}

Point GetIntersection(Line a , Line b)
{
    Vector u = a.p-b.p;
    double t = Cross(b.v , u)/Cross(a.v , b.v);
    return a.p+a.v*t;
}

int HalfplaneIntersection(Line *L , int n , Point *poly)
{
    sort(L , L+n);
    int first , last;
    Point *p = new Point[n];
    Line *q = new Line[n];
    q[first=last=0] = L[0];
    for(int i=1 ; i<n ; i++){
        while(first<last && !OnLeft(L[i] , p[last-1])) last--;
        while(first<last && !OnLeft(L[i] , p[first])) first++;
        q[++last] = L[i];
        if(fabs(Cross(q[last].v , q[last-1].v))<eps){
            last--;
            if(OnLeft(q[last] , L[i].p)) q[last]=L[i];
        }
        if(first < last) p[last-1] = GetIntersection(q[last-1] , q[last]);
    }
    while(first<last && !OnLeft(q[first] , p[last-1])) last--;
    if(last-first<=1) return 0;
    p[last] = GetIntersection(q[last] , q[first]);
    int m=0;
    for(int i=first ; i<=last ; i++) poly[m++] = p[i];
    return m;
}

int main()
{
   // freopen("in.txt" , "r" , stdin);
    int T , n;
    scanf("%d" , &T);
    while(T--)
    {
        scanf("%d" , &n);
        for(int i=0 ; i<n ; i++) scanf("%lf%lf" , &p[i].x , &p[i].y);
        p[n] = p[0];
        for(int i=0 ; i<n ; i++) line[i] = Line(p[i] , p[i]-p[i+1]);
        if(HalfplaneIntersection(line , n , poly)) puts("YES");
        else puts("NO");
    }
}
View Code

poj 1474

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <cmath>
 6 
 7 using namespace std;
 8 #define N 105
 9 #define ll long long
10 #define eps 1e-9
11 
12 int dcmp(double x)
13 {
14     if(fabs(x)<eps) return 0;
15     else return x<0?-1:1;
16 }
17 
18 struct Point{
19     double x,y;
20     Point(double x=0 , double y=0):x(x),y(y){}
21 }p[N] , poly[N];
22 
23 typedef Point Vector;
24 
25 struct Line{
26     Point p;
27     Vector v;
28     double ang;
29     Line(){}
30     Line(Point p , Vector v):p(p),v(v){ang = atan2(v.y , v.x);}
31     bool operator<(const Line &m) const{
32         return dcmp(ang-m.ang)<0;
33     }
34 }line[N];
35 
36 Vector operator+(Vector a , Vector b){return Vector(a.x+b.x , a.y+b.y);}
37 Vector operator-(Vector a , Vector b){return Vector(a.x-b.x , a.y-b.y);}
38 Vector operator*(Vector a , double b){return Vector(a.x*b , a.y*b);}
39 Vector operator/(Vector a , double b){return Vector(a.x/b , a.y/b);}
40 
41 double Cross(Vector a , Vector b){return a.x*b.y-a.y*b.x;}
42 
43 bool OnLeft(Line L , Point P)
44 {
45     return dcmp(Cross(L.v , P-L.p))>=0;
46 }
47 
48 Point GetIntersection(Line a , Line b)
49 {
50     Vector u = a.p-b.p;
51     double t = Cross(b.v , u)/Cross(a.v , b.v);
52     return a.p+a.v*t;
53 }
54 
55 int HalfplaneIntersection(Line *L , int n , Point *poly)
56 {
57     sort(L , L+n);
58     int first , last;
59     Point *p = new Point[n];
60     Line *q = new Line[n];
61     q[first=last=0] = L[0];
62     for(int i=1 ; i<n ; i++){
63         while(first<last && !OnLeft(L[i] , p[last-1])) last--;
64         while(first<last && !OnLeft(L[i] , p[first])) first++;
65         q[++last] = L[i];
66         if(fabs(Cross(q[last].v , q[last-1].v))<eps){
67             last--;
68             if(OnLeft(q[last] , L[i].p)) q[last]=L[i];
69         }
70         if(first < last) p[last-1] = GetIntersection(q[last-1] , q[last]);
71     }
72     while(first<last && !OnLeft(q[first] , p[last-1])) last--;
73     if(last-first<=1) return 0;
74     p[last] = GetIntersection(q[last] , q[first]);
75     int m=0;
76     for(int i=first ; i<=last ; i++) poly[m++] = p[i];
77     return m;
78 }
79 
80 int main()
81 {
82    // freopen("in.txt" , "r" , stdin);
83     int n , cas=0 , flag=0;
84     while(scanf("%d" , &n) , n)
85     {
86         if(flag) puts("");
87         flag=1;
88         for(int i=0 ; i<n ; i++) scanf("%lf%lf" , &p[i].x , &p[i].y);
89         p[n] = p[0];
90         for(int i=0 ; i<n ; i++) line[i] = Line(p[i] , p[i]-p[i+1]);
91         printf("Floor #%d
" , ++cas);
92         if(HalfplaneIntersection(line , n , poly)) puts("Surveillance is possible.");
93         else puts("Surveillance is impossible.");
94     }
95 }
View Code

poj 1279

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <cmath>
  6 
  7 using namespace std;
  8 #define N 1505
  9 #define ll long long
 10 #define eps 1e-9
 11 
 12 int dcmp(double x)
 13 {
 14     if(fabs(x)<eps) return 0;
 15     else return x<0?-1:1;
 16 }
 17 
 18 struct Point{
 19     double x,y;
 20     Point(double x=0 , double y=0):x(x),y(y){}
 21 }p[N] , poly[N];
 22 
 23 typedef Point Vector;
 24 
 25 struct Line{
 26     Point p;
 27     Vector v;
 28     double ang;
 29     Line(){}
 30     Line(Point p , Vector v):p(p),v(v){ang = atan2(v.y , v.x);}
 31     bool operator<(const Line &m) const{
 32         return dcmp(ang-m.ang)<0;
 33     }
 34 }line[N];
 35 
 36 Vector operator+(Vector a , Vector b){return Vector(a.x+b.x , a.y+b.y);}
 37 Vector operator-(Vector a , Vector b){return Vector(a.x-b.x , a.y-b.y);}
 38 Vector operator*(Vector a , double b){return Vector(a.x*b , a.y*b);}
 39 Vector operator/(Vector a , double b){return Vector(a.x/b , a.y/b);}
 40 
 41 double Cross(Vector a , Vector b){return a.x*b.y-a.y*b.x;}
 42 
 43 bool OnLeft(Line L , Point P)
 44 {
 45     return dcmp(Cross(L.v , P-L.p))>=0;
 46 }
 47 
 48 Point GetIntersection(Line a , Line b)
 49 {
 50     Vector u = a.p-b.p;
 51     double t = Cross(b.v , u)/Cross(a.v , b.v);
 52     return a.p+a.v*t;
 53 }
 54 
 55 int HalfplaneIntersection(Line *L , int n , Point *poly)
 56 {
 57     sort(L , L+n);
 58     int first , last;
 59     Point *p = new Point[n];
 60     Line *q = new Line[n];
 61     q[first=last=0] = L[0];
 62     for(int i=1 ; i<n ; i++){
 63         while(first<last && !OnLeft(L[i] , p[last-1])) last--;
 64         while(first<last && !OnLeft(L[i] , p[first])) first++;
 65         q[++last] = L[i];
 66         if(fabs(Cross(q[last].v , q[last-1].v))<eps){
 67             last--;
 68             if(OnLeft(q[last] , L[i].p)) q[last]=L[i];
 69         }
 70         if(first < last) p[last-1] = GetIntersection(q[last-1] , q[last]);
 71     }
 72     while(first<last && !OnLeft(q[first] , p[last-1])) last--;
 73     if(last-first<=1) return 0;
 74     p[last] = GetIntersection(q[last] , q[first]);
 75     int m=0;
 76     for(int i=first ; i<=last ; i++) poly[m++] = p[i];
 77     return m;
 78 }
 79 
 80 double calArea(Point *p , int n)
 81 {
 82     if(!n) return 0;
 83     double ret = 0;
 84     for(int i=2 ; i<n ; i++){
 85         ret += Cross(p[i-1]-p[0],p[i]-p[0]);
 86     }
 87     return ret/2;
 88 }
 89 
 90 int main()
 91 {
 92    // freopen("in.txt" , "r" , stdin);
 93     int T , n ;
 94     scanf("%d" , &T);
 95     while(T--)
 96     {
 97         scanf("%d" , &n);
 98         for(int i=0 ; i<n ; i++) scanf("%lf%lf" , &p[i].x , &p[i].y);
 99         p[n] = p[0];
100         for(int i=0 ; i<n ; i++) line[i] = Line(p[i] , p[i]-p[i+1]);
101         int cnt = HalfplaneIntersection(line , n , poly);
102         printf("%.2f
" , calArea(poly , cnt));
103     }
104 }
View Code
原文地址:https://www.cnblogs.com/CSU3901130321/p/4668890.html