POJ 3335 半面相交

题意:给你一个多边形,问是否存在区域能看到多边形的任意位置,也就是存不存在内核。

将每条边看做一个半面求半面相交。如果存在那么半面至少三个。

#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int mm=111;
typedef double DIY;
struct point
{
    DIY x,y;
    point() {}
    point(DIY _x,DIY _y):x(_x),y(_y) {}
} g[mm];
point MakeVector(point &P,point &Q)
{
    return point(Q.x-P.x,Q.y-P.y);
}
DIY CrossProduct(point P,point Q)
{
    return P.x*Q.y-P.y*Q.x;
}
DIY MultiCross(point P,point Q,point R)
{
    return CrossProduct(MakeVector(Q,P),MakeVector(Q,R));
}
struct halfPlane
{
    point s,t;
    double angle;
    halfPlane() {}
    halfPlane(point _s,point _t):s(_s),t(_t) {}
    halfPlane(DIY sx,DIY sy,DIY tx,DIY ty):s(sx,sy),t(tx,ty) {}
    void GetAngle()
    {
        angle=atan2(t.y-s.y,t.x-s.x);
    }
} hp[mm],q[mm];
point IntersectPoint(halfPlane P,halfPlane Q)
{
    DIY a1=CrossProduct(MakeVector(P.s,Q.t),MakeVector(P.s,Q.s));
    DIY a2=CrossProduct(MakeVector(P.t,Q.s),MakeVector(P.t,Q.t));
    return point((P.s.x*a2+P.t.x*a1)/(a2+a1),(P.s.y*a2+P.t.y*a1)/(a2+a1));
}
bool cmp(halfPlane P,halfPlane Q)
{
    if(fabs(P.angle-Q.angle)<1e-8)
        return MultiCross(P.s,P.t,Q.s)>0;
    return P.angle<Q.angle;
}
bool IsParallel(halfPlane P,halfPlane Q)
{
    return fabs(CrossProduct(MakeVector(P.s,P.t),MakeVector(Q.s,Q.t)))<1e-8;
}
void HalfPlaneIntersect(int n,int &m)
{
    sort(hp,hp+n,cmp);
    int i,l=0,r=1;
    for(m=i=1; i<n; ++i)
        if(hp[i].angle-hp[i-1].angle>1e-8)hp[m++]=hp[i];
    n=m;
    m=0;
    q[0]=hp[0],q[1]=hp[1];
    for(i=2; i<n; ++i)
    {
        if(IsParallel(q[r],q[r-1])||IsParallel(q[l],q[l+1]))return;
        while(l<r&&MultiCross(hp[i].s,hp[i].t,IntersectPoint(q[r],q[r-1]))>0)--r;
        while(l<r&&MultiCross(hp[i].s,hp[i].t,IntersectPoint(q[l],q[l+1]))>0)++l;
        q[++r]=hp[i];
    }
    while(l<r&&MultiCross(q[l].s,q[l].t,IntersectPoint(q[r],q[r-1]))>0)--r;
    while(l<r&&MultiCross(q[r].s,q[r].t,IntersectPoint(q[l],q[l+1]))>0)++l;
    q[++r]=q[l];
    for(i=l; i<r; ++i)
        g[m++]=IntersectPoint(q[i],q[i+1]);
}
int main()
{
    int t,n,m;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=0; i<n; i++)
            scanf("%lf%lf",&g[i].x,&g[i].y);
        for(int i=0; i<n; i++)
        {
            hp[i]=halfPlane(g[(i+1)%n],g[i]);
            hp[i].GetAngle();
        }
        HalfPlaneIntersect(n,m);
        puts(m>2?"YES":"NO");
    }
    return 0;
}
时间: 2024-09-20 21:25:43

POJ 3335 半面相交的相关文章

POJ 1474 半面相交

题意:给定一个多边形判断是否存在内核. 模板题.判断最后半面相交的半面数至少3个就行. #include<cmath> #include<cstdio> #include<iostream> #include<algorithm> using namespace std; const int mm=111; typedef double DIY; struct point { DIY x,y; point() {} point(DIY _x,DIY _y):

POJ 3130 半面相交

题意:很明显判断多边形是否存在内核. 将每个边看做一个半面,判断版面是否大于2即可. #include<cmath> #include<cstdio> #include<iostream> #include<algorithm> using namespace std; const int mm=111; typedef double DIY; struct point { DIY x,y; point() {} point(DIY _x,DIY _y):x

POJ 3525 二分+半面相交

题意:给定一个凸多边形问能包裹圆的最大半径. 将每条边向内移动距离d,知道半面相交的内核不存在,确定最大的d并且达到精度就可以了. #include<cmath> #include<cstdio> #include<iostream> #include<algorithm> using namespace std; const int mm=111; typedef double DIY; struct point { DIY x,y; point() {}

HDU 4316 凸包+半面相交

题意:一个房间,在房间顶部有三个摄像头,房间有放有一个凸多面体的机器,问这个机器对摄像头在地面造成盲点的面积.房间顶部z=100,地面z=0. 首先根据空间直线方程(x-x1)/(x1-x2)=(y-y1)/(y1-y2)=(z-z1)/(z1-z2) 求出每个摄像头与凸多面体连线与地面(z=0)的交点.在对这个摄像头在地面的交点求凸包,这个区域就个该摄像头盲区的面积,但是需要求三个盲区面积的交,所以把3个凸包的边变成半面,求最后的半面交,得出相交的多边形再求面积即为答案.上来就是甩模板啊..

POJ 1066 判断线段相交

题意:有个考古队进金字塔里盗墓,大小100*100,样图是一个俯视图,给了财宝坐标,又给了各个墙.题目规定考古队在每面墙的中点处开一个洞,这样就避免了两墙交点的情况,求最小的凿墙数目. 很明显,枚举连接四面两个墙之间中点与宝藏的线段,求出这种线段与墓里墙相交的最小值.其实可以不用枚举中点,直接用墙的端点与宝藏相连的线段就行,细想一想可以想明白. #include <iostream> #include<cstdio> #include<cstring> #include

POJ 3449 判断多边形相交

题意:给你多边形 让你判断每个多边形分别有几个多边形与它相交. 这题的输入输出恶心,另外给出正方形对角点求出另两个点的公式 已知一正方形两对角顶点A.C的坐标分别是(ax, ay).(cx, xy): 求B.D坐标(bx, by).(dx, dy):           bx = (cx+ax+cy-ay)/2;           by = (cy+ay+ax-cx)/2;           dx = (cx+ax+ay-cy)/2;           dy = (cy+ay+cx-ax)

POJ 2451 求半面交

题意:求半面想交后的面积,题目数据较大,使用o(n*logn)算法. 这题WA两次忘了m<3的情况,不应该啊= = . #include<cmath> #include<cstdio> #include<iostream> #include<algorithm> using namespace std; const int mm=20005; typedef double DIY; struct point { DIY x,y; point() {}

POJ 2653 暴力判断线段相交

题意是按照输入的先后顺序放木棍,然后输出最上层的木棍,何为最上层,就是木棍上方没有木棍和它相交就行. 这题坑爹啊,一直TLE后来才发现最上层木棍不是底下的木棍数最多而是只要上方没有木棍就行.所以只需要开一个标记数组从前往后如果后面有与它相交的那么这个木棍肯定不是最上层的,知道这些再知道线段相交的模板就可以A了. #include <iostream> #include<cstdio> #include<cstring> #include<algorithm>

POJ 3304 判断直线与线段相交

题意:问存不存在一条直线,各个线段在直线上的投影有公共部分,也就是判断是否存在一条直线将所有线段都相交. 枚举所有端点构成的直线如果有一条直线相交所有线段那么就存在. #include <iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; #define eps 1e-8 typedef doub