码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 3130 How I Mathematician Wonder What You Are!

时间:2019-02-23 10:36:33      阅读:174      评论:0      收藏:0      [点我收藏+]

标签:++   去重   for   过程   amp   存在   opera   sort   极角   

明明是准备打 POJ 3335的 结果3335始终WA反而代码该了一行把此题过了。。

 

/*
半平面交 
1.首先规定逆时针给点 判断的时候直接求有向面积 面积为负则是顺时针给的点 
2.极角排序 (可以去重 留下靠左的一个)
3.模拟双端队列 判断队列尾部两线的交点和头部两线的交点在新加入线段哪一侧 
    左侧即合法 直接加入 右侧即不合法 删掉堆尾
4.因为我们 3 过程中始终保持队列数量至少为2 所以最后判断头部和尾部的合法性
    剩下的边<=2条的话 说明不存在内核
*/
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=150;
const double eps=1e-9;
struct Point
{
    double x,y;Point(){}
    Point(double _x,double _y){x=_x,y=_y;}
}p[N];
struct Line
{
    Point s,e;Line(){}
    Line(Point _s,Point _e){s=_s,e=_e;} 
}l[N],q[N];
int n,T;
Point operator - (Point A,Point B) {return Point(A.x-B.x,A.y-B.y);} 
double operator ^ (Point A,Point B) {return A.x*B.y-A.y*B.x;} 
Point operator & (Line A,Line B)
{
    Point C=A.s;
    double t=((A.s-B.s)^(B.s-B.e))/((A.s-A.e)^(B.s-B.e));
    C.x+=(A.e.x-A.s.x)*t; C.y+=(A.e.y-A.s.y)*t;
    return C;
}
bool Isf() // 判断给出的点是否是逆时针的
{
    double res=0;
    for(int i=2;i<n;i++) res+=((p[i+1]-p[1])^(p[i]-p[1]));
    return res>eps;
}
double getangle(Point a)
{
    return atan2(a.y,a.x); // atan2(y,x) 得到(0,0)->(x,y) 的极角
}
bool cmp(Line a,Line b)
{
    double c1=getangle(a.e-a.s),c2=getangle(b.e-b.s);
    if(fabs(c1-c2)<eps) return ((a.e-a.s)^(b.e-b.s))>eps;
    return c1<c2;
}

bool check(Line a,Line b,Line c) // 判断 a,b的交点是否在c的左侧(叉积为正)
{
    Point d=a&b; return ((d-c.s)^(c.e-c.s))>=eps;
}
bool solve()
{
    sort(l+1,l+n+1,cmp);
    int L=1,R=2; q[1]=l[1],q[2]=l[2];
    for(int i=3;i<=n;i++)
    {
        while(R-L>=1&&!check(q[R],q[R-1],l[i])) R--;
        while(R-L>=1&&!check(q[L],q[L+1],l[i])) L++;
        q[++R]=l[i];
    }
    while(R-L>=1&&!check(q[L],q[L+1],q[R])) L++;
    while(R-L>=1&&!check(q[R],q[R-1],q[L])) R--;
    return R-L>=2;
}
int main()
{
    while(scanf("%d",&n))
    {
        if(n==0) break;
        for(int i=1;i<=n;i++)
        {
            double x,y;
            scanf("%lf%lf",&x,&y);
            p[i]=Point(x,y);
        }
        if(!Isf()) for(int i=1;i<=(n>>1);i++) swap(p[i],p[n-i+1]);
        p[n+1]=p[1]; for(int i=1;i<=n;i++) l[i]=Line(p[i],p[i+1]);
        if(solve()) puts("1"); else puts("0");
        
    }
    return 0;
}

 

POJ 3130 How I Mathematician Wonder What You Are!

标签:++   去重   for   过程   amp   存在   opera   sort   极角   

原文地址:https://www.cnblogs.com/lxy8584099/p/10421746.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!