POJ1279 Art Gallery

来源:互联网 发布:ping命令是哪个端口 编辑:程序博客网 时间:2024/06/08 12:48

这道题一定要好好纪念一下,改代码改了一整天。。。。

代码写出来后一直WA,原来以为是精度问题或者程序哪个地方出了点小错误,毕竟第一次写排序增量算法

然后一直在改,后来实在找不出了,去看了discuss,有人说把g++改成c++就过了

然后自己也试了一遍,就过了。。。。

后来搜了下g++和c++的区别,得知g++输出浮点数时最好用%f,要不然有时候会出错。

然后把输出改成了%f,用g++提交,过了。。。

#include<stdio.h>#include<math.h>#include<string.h>#include<algorithm>using namespace std;const double eps=1e-8;struct Point {    double x,y;    Point(){};    Point(double xx,double yy) {        x=xx;   y=yy;    }    double operator ^(const Point b) const {        return x*b.y-y*b.x;    }    double operator *(const Point b) const {        return x*b.x+y*b.y;    }};struct Line {    Point s,e;    double angle;};int n,m,ln,order[1505],dq[1505],bot,top;Point p[1505];Line l[1505];double multi(Point p,Point a,Point b) {//点b在直线p-a的左边时值>0    return (a.x-p.x)*(b.y-p.y)-(a.y-p.y)*(b.x-p.x);}int dblcmp(double a) {    if (fabs(a)<eps) return 0;    return a>0?1:-1;}//按极角从小到大排序//对于相同角度的两个半平面(a1a2,b1b2),只需要保留被其他角度相同的半平面覆盖的那一个int cmp(int a,int b) {    int d=dblcmp(l[a].angle-l[b].angle);    if (!d) return dblcmp(multi(l[a].s,l[b].s,l[b].e))<0;    return d<0;}int EqualPoint(Point a, Point b) {//两点相等    return dblcmp(a.x - b.x) == 0 && dblcmp(a.y - b.y) == 0;}void AddLine(Point s,Point e){    l[ln].s=s;    l[ln].e=e;    l[ln].angle=atan2(e.y-s.y,e.x-s.x);    order[ln]=ln;    ln++;}Point Intersect(Line l1,Line l2) {    /*double s1,s2;    s1=multi(a.s,a.e,b.s);    s2=multi(a.s,a.e,b.e);    return Point((a.s.x*s2+a.e.x*s1)/(s1+s2),(a.s.y*s2+a.e.y*s1)/(s1+s2));*/    double dot1, dot2;    Point p;    dot1 = multi(l2.s, l1.e, l1.s);    dot2 = multi(l1.e, l2.e, l1.s);    p.x = (l2.s.x * dot2 + l2.e.x * dot1) / (dot2 + dot1);    p.y = (l2.s.y * dot2 + l2.e.y * dot1) / (dot2 + dot1);    return p;}int Judge(Line l0,Line l1,Line l2) {    Point p=Intersect(l1,l2);    return dblcmp(multi(l0.s,l0.e,p))>0;//因为该题是顺时针给出的点,所以p在直线左边即<0时,top--}void HPI(){int i,j;    sort(order,order+ln,cmp);    for(i=1,j=0;i<n;i++) {        if (dblcmp(l[order[i]].angle-l[order[j]].angle)>0) order[++j]=order[i];        ln=j+1;    }    dq[0]=order[0];    dq[1]=order[1];    bot=0,top=1;    for( i=2;i<ln;i++) {        while(bot<top && Judge(l[order[i]],l[dq[top-1]],l[dq[top]]))            top--;        while(bot<top && Judge(l[order[i]],l[dq[bot+1]],l[dq[bot]]))            bot++;        dq[++top]=order[i];    }    //对最后加进去的点后进行处理    while(bot<top && Judge(l[dq[bot]],l[dq[top-1]],l[dq[top]])) top--;    while(bot<top && Judge(l[dq[top]],l[dq[bot+1]],l[dq[bot]])) bot++;    //printf("%d %d\n",bot,top);m=0;    if (top<=bot+1) return;//不能构成封闭的多边形    //最终的核即各线段所在直线的交点    for( i=bot;i<top;i++) p[m++]=Intersect(l[dq[i]],l[dq[i+1]]);    if (top>bot+1) p[m++]=Intersect(l[dq[bot]],l[dq[top]]);//即最终的线段大于2条,可形成环时    m=unique(p,p+m,EqualPoint)-p;}double xmul(Point p0,Point p1,Point p2){    return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);}int main() {    #ifndef ONLINE_JUDGE    freopen("in.txt","r",stdin);    #endif // ONLINE_JUDGE    int T,i;    scanf("%d",&T);    while(T--) {        scanf("%d",&n);        ln=0;        memset(dq,0,sizeof(dq));        memset(order,0,sizeof(order));        double s=0;        for(i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);        /*for(inti=0;i<n;i++) s+=p[i]^p[(i+1)%n];        if (s>0){          for(int i=0;i<n/2;i++) swap(p[i],p[n-1-i]);        }*/        p[n]=p[0];        for(i=0;i<n;i++) AddLine(p[i],p[i+1]);        HPI();        s=0;        for(i=0;i<m;i++) {            s+=p[i]^p[(i+1)%m];        }        if (fabs(s)<eps) s=0.0;        printf("%.2lf\n",fabs(s/2.0));    }    return 0;}


0 0
原创粉丝点击