POJ 2451 Uyuw's Concert

本文通过修改极角排序方式及使用xmul函数替代原有向量判断方法,解决了凸包问题。作者分享了调整代码后的成功经验,并建议未来采用xmul函数进行点位置判断。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

把别人的代码和自己的代码不断对比,实在不知道问题出在哪里,太坑了

就改了两个地方

一个是把判断点在向量左右的方法改成了xmul函数,我仔细看过,代进去公式完全一样的

还有一个地方就是把极角排序改成了按从大到小

就改了这两个地方就AC了

总结就是以后还是用xmul好了

#include<stdio.h>
#include<math.h>
#include<algorithm>
#define zero(a) fabs(a)<eps
using namespace std;
const double eps=1e-10;
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;
    }
    Point operator-(const Point b)const{
        return Point(x-b.x,y-b.y);
    }
};
struct Line {
    Point s,e;
    double angle;
    Line(){};
    Line(Point ss,Point ee){s=ss;e=ee;}
    Point operator &(const Line b)const {
        Point res=s;
        double t=((s-b.e)^(b.s-b.e))/((s-e)^(b.s-b.e));
        res.x+=(e.x-s.x)*t;
        res.y+=(e.y-s.y)*t;
        return res;
    }
    void puts(){
        printf("%.2f %.2f %.2f %.2f  %f\n",s.x,s.y,e.x,e.y,angle);
    }
};
int n;
Line dq[20005],l[20005];
Point p[20005];
int cmp(Line a,Line b){
    if (fabs(a.angle-b.angle)<eps) return ((a.e-a.s)^(b.s-a.s))<-eps;
    else return a.angle>b.angle;
}
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);
}
/*bool cmp(Line s1,Line s2){
    //先按极角排序
    if(s1.angle>s2.angle) return true;
    //极角相等,内侧的在前
    else if(zero(s1.angle-s2.angle)&&xmul(s2.s,s2.e,s1.e)>-eps) return true;
    return false;
}*/
void HPI(){
    sort(l,l+n,cmp);
    int ln=0;
    for(int i=1,j=0;i<n;i++) {
        if (!zero(l[i].angle-l[j].angle)) l[++j]=l[i];
        ln=j+1;
    }
    n=ln;
    //for(int i=0;i<n;i++) l[i].puts();
    int bot=0,top=1;
    dq[0]=l[0];    dq[1]=l[1];
    /*for(int i=2;i<n;i++) {
        while(bot<top && ((l[i].e-l[i].s)^((dq[top]&dq[top-1])-l[i].s))<-eps) top--;
        while(bot<top && ((l[i].e-l[i].s)^((dq[bot]&dq[bot+1])-l[i].s))<-eps) bot++;
        dq[++top]=l[i];
    }
    while(bot<top && ((l[bot].e-l[bot].s)^((dq[top]&dq[top-1])-l[bot].s))<-eps) top--;
    while(bot<top && ((l[top].e-l[top].s)^((dq[bot]&dq[bot+1])-l[top].s))<-eps) bot++;*/
        for(int i=2;i<n;i++){
        while(bot<top&&xmul(l[i].s,l[i].e,(dq[top]&dq[top-1]))<-eps) top--;
        while(bot<top&&xmul(l[i].s,l[i].e, (dq[bot]&dq[bot+1]))<-eps) bot++;
        dq[++top]=l[i];
    }
    while(bot<top&&xmul(dq[bot].s,dq[bot].e, (dq[top]&dq[top-1]))<-eps) top--;
    while(bot<top&&xmul(dq[top].s,dq[top].e, (dq[bot]&dq[bot+1]))<-eps) bot++;

    dq[top+1]=dq[bot];
    int cnt=0;
    //for(int i=bot;i<=top;i++) l[i].puts();
    for(int i=bot;i<=top;i++) p[cnt++]=dq[i]&dq[i+1];
    //printf("%d ",cnt);
    p[cnt]=p[0];
    if (top<=bot+1) cnt=0;
    double s=0;
    for(int i=0;i<cnt;i++) s+=p[i]^p[i+1];
    s=fabs(s*0.5);
    printf("%.1f\n",s);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif // ONLINE_JUDGE
    while(scanf("%d",&n)!=EOF) {
        l[0]=Line(Point(0,0),Point(10000,0));   l[n].angle=atan2(l[n].e.y-l[n].s.y,l[n].e.x-l[n].s.x);
        l[0+1]=Line(Point(10000,0),Point(10000,10000)); l[0+1].angle=atan2(l[0+1].e.y-l[0+1].s.y,l[0+1].e.x-l[0+1].s.x);
        l[0+2]=Line(Point(10000,10000),Point(0,10000)); l[0+2].angle=atan2(l[0+2].e.y-l[0+2].s.y,l[0+2].e.x-l[0+2].s.x);
        l[0+3]=Line(Point(0,10000),Point(0,0)); l[0+3].angle=atan2(l[0+3].e.y-l[0+3].s.y,l[0+3].e.x-l[0+3].s.x);
        for(int i=0;i<n;i++) {
            scanf("%lf%lf%lf%lf",&l[i+4].s.x,&l[i+4].s.y,&l[i+4].e.x,&l[i+4].e.y);
            l[i+4].angle=atan2(l[i+4].e.y-l[i+4].s.y,l[i+4].e.x-l[i+4].s.x);
        }

        n=n+4;
        HPI();
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值