POJ1279 Art Gallery

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

代码写出来后一直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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值