【CTSC1998】监视摄像机

多边形的核,半平面交

题目大意:

给定一个多边形,问其内部是否存在一个点,其与多边形内部、边、点的连线上不存在另一条边。

题解:

就是要判断多边形内部是否存在核。

不难发现,对每个点,能看到这个点及其夹边的所有点构成的区域,恰是两条夹边的半平面的交。

那我们对每个点,都有这么一部分半平面,这些半平面的交的部分,就是合法区域。

我们只要求这些多边形的边是否存在半平面交即可。

观察数据较小,可以使用一些比较暴力的算法。

一个大小有限的半平面交,显然是一个凸包,这些凸包上的点一定是半平面的直线的交点。

我们把这些所有交点拿出来,然后对每个交点,如果它在半平面交内部,则所有半平面都包含它。枚举半平面,叉积判断其是否在半平面内部即可。

最后检查是否有点在半平面内部即可。

时间复杂度 $O(n^3)$。足以承受本题的数据范围。

Code:

#include<cstdio>
#include<vector>
using namespace std;
const int N=105;
int n;
template<typename T>
struct point{
    T x,y;
    inline point operator-(const point&r)const{return(point){x-r.x,y-r.y};}
};
point<int>d[N];
template<typename T>
inline T cross(const point<T>&a,const point<T>&b){return a.x*b.y-a.y*b.x;}
inline int Next(int x){return(x%n+1);}
vector<point<double> >vec;
bool vis[N*N*5];
point<double>get(point<int>a1,point<int>a2,point<int>b1,point<int>b2){
    if(a1.x==a2.x&&b1.x==b2.x)return(point<double>){23333,23333};
    double k_a=(a2.y-a1.y)*1./(a2.x-a1.x),k_b=(b2.y-b1.y)*1./(b2.x-b1.x);
    double b_a=a1.y-k_a*a1.x,b_b=b1.y-k_b*b1.x;
    if(a1.x==a2.x)return(point<double>){a1.x,a1.x*k_b+b_b};
    if(b1.x==b2.x)return(point<double>){b1.x,b1.x*k_a+b_a};
    double x=(b_b-b_a)/(k_a-k_b);
    return(point<double>){x,x*k_a+b_a};
}
int main(){
    int T=0;
    while(scanf("%d",&n),n){
        vec.clear();
        for(int i=n;i;--i)
            scanf("%d%d",&d[i].x,&d[i].y);
        for(int i=1;i<=n;++i){
            int j=Next(i);
            for(int k=j;Next(k)!=i;k=Next(k)){
                point<double>s=get(d[i],d[j],d[k],d[Next(k)]);
                if(s.x*s.y<1e9)
                vec.push_back(s);
            }
        }
        for(int i=0;i<vec.size();++i)vis[i]=1;
        for(int i=1;i<=n;++i){
            int j=Next(i);
            for(int id=0;id<vec.size();++id)if(vis[id]){
                point<double>a=(point<double>){d[j].x-d[i].x,d[j].y-d[i].y};
                point<double>b=(point<double>){vec[id].x-d[i].x,vec[id].y-d[i].y};
                double cr=a.x*b.y-a.y*b.x;
                if(cr+1e-9<0)vis[id]=0;
            }
        }
        bool ok=0;
        for(int i=0;i<vec.size()&&!ok;++i)ok=vis[i];
        printf("Room #%d:\nSurveillance is %spossible.\n\n",++T,(ok)?"":"im");
    }
    return 0;
}