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

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

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

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

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

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

譬如:

比如这个多边形

蓝色区域便是内核

这样利用半平面交的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");
    }
}

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\n" , ++cas);
92         if(HalfplaneIntersection(line , n , poly)) puts("Surveillance is possible.");
93         else puts("Surveillance is impossible.");
94     }
95 }

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\n" , calArea(poly , cnt));
103     }
104 }

时间: 2024-12-15 01:18:31

半平面交 求多边形内核问题的相关文章

POJ 1474 Video Surveillance 半平面交求多边形内核存在性

题目大意:一个楼有很多层,每一层是一个多多边形,问每一层是否有点能够看到这一层的全貌. 思路:半平面交解多边形内核存在性,裸题.题中怎么没写数据范围?..让我还re几次.. CODE: #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 3010 #define EPS 1e-8 #de

POJ 3335 Rotating Scoreboard 半平面交求多边形内核

题目大意:多边形求内核模板题 思路:半平面交,我用的是O(nlogn)的半平面交,但是有一个问题,就是当多边形内核是一个点的时候,半平面交所得到的答案是空集合,但是输出应该是yes,实在没有什么好的解决方法,最后只能把所有直线向右移动,然后在求内核.但是这样做eps的不同取值有的时候能A有的时候不能A.有没有什么好的解决方法啊!!!求解答啊!!! CODE: #include <cmath> #include <cstdio> #include <cstring> #i

POJ 3130 How I Mathematician Wonder What You Are! 半平面交求多边形内核是否存在

题目大意:定义一种多边形,叫做星形多边形.这种多边形就是有内核的多边形.给出一些多边形,问是否是星形多边形. 思路:利用半平面交求解.PS:我的第一个多边形内核的代码不对..一定要看这个,这个是我看了学长的代码之后才发现之前的代码的问题的,这个也不用微调,是准确值,总值千万不要去看前面的那篇!!!! 由于内核中的所有点到图形上所有点的连线之间不能有边阻挡,所以为了满足任意一条边,需要满足内核的点必须在这条边所在直线的左边,所以将所有组成多边形的边所在的直线进行半平面交即可.由于一个多边形的内核也

POJ 1474 Video Surveillance 半平面交求多边形是否有核

裸的半平面交求多边形是否有核. 多边形的核: 在多边形核上的点可以看到多边形的所有顶点,凸多边形的核显然就是多边形本身. 多边形的核是一个凸包,对多边形的所有边都做向着多边形的半平面交在判断一下是否构成凸包就可以了 一样的题目还有POJ3335 Video Surveillance Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3438   Accepted: 1523 Description A friend of y

POJ 3335 半平面交求多边形的核

Rotating Scoreboard Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4899   Accepted: 1946 Description This year, ACM/ICPC World finals will be held in a hall in form of a simple polygon. The coaches and spectators are seated along the ed

POJ 3130 How I Mathematician Wonder What You Are!(半平面交求多边形的核)

题目链接 题意 : 给你一个多边形,问你该多边形中是否存在一个点使得该点与该多边形任意一点的连线都在多边形之内. 思路 : 与3335一样,不过要注意方向变化一下. 1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <math.h> 5 6 using namespace std ; 7 8 struct node 9 { 10 double x; 11 d

POJ 3335 Rotating Scoreboard(半平面交求多边形核)

题目链接 题意 : 给你一个多边形,问你在多边形内部是否存在这样的点,使得这个点能够看到任何在多边形边界上的点. 思路 : 半平面交求多边形内核. 半平面交资料 关于求多边形内核的算法 什么是多边形的内核? 它是平面简单多边形的核是该多边形内部的一个点集,该点集中任意一点与多边形边界上一点的连线都处于这个多边形内部.就是一个在一个房子里面放一个摄像 头,能将所有的地方监视到的放摄像头的地点的集合即为多边形的核. 如上图,第一个图是有内核的,比如那个黑点,而第二个图就不存在内核了,无论点在哪里,总

POJ 1279 Art Gallery(半平面交求多边形核的面积)

题目链接 题意 : 求一个多边形的核的面积. 思路 : 半平面交求多边形的核,然后在求面积即可. #include <stdio.h> #include <string.h> #include <iostream> #include <math.h> using namespace std ; struct node { double x; double y ; } p[1510],temp[1510],newp[1510];//p是最开始的多边形的每个点,

POJ 1279 Art Gallery 半平面交求多边形核

第一道半平面交,只会写N^2. 将每条边化作一个不等式,ax+by+c>0,所以要固定顺序,方便求解. 半平面交其实就是对一系列的不等式组进行求解可行解. 如果某点在直线右侧,说明那个点在区域内,否则出现在左边,就可能会有交点,将交点求出加入. //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include <stdio.h> #include <iostream> #inc