bzoj1007 类半平面交

之前直接套半平面交的板子怎么都过不了

后来看博客说这题精度要求太高要去掉eps什么的。。。但我还是WA

后来随便写一发,直接用A排序就过了

之后纠结半平面交的板子为撒错了

首先吧hpicmp的排序改成用A排序,而不是tan2计算出来的k

后来发现不能把上口封住,会出问题。

而由于没有封口,导致下面的判断首尾合不合法也要去掉

这样才能过。。。计算几何急死人系列,上面是随手写的代码,下面是魔改半平面交的代码

#include<bits/stdc++.h>
#define maxl 50010
#define eps 1e-8
using namespace std;

inline int sgn(double x)
{
	if(x>-eps && x<eps) return 0;
	if(x>0) return 1;
	else	return -1;
}

struct point
{
	double x,y;
	point(double a=0,double b=0)
	{
		x=a,y=b;
	}
	point operator + (const point b)const
	{
		return point(x+b.x,y+b.y);
	}
	friend point operator * (const double t,const point p)
	{
		return point(t*p.x,t*p.y);
	}
	point operator - (const point b)const
	{
		return point(x-b.x,y-b.y);
	}
	bool operator == (const point b)const
	{
		return sgn(x-b.x)==0 && sgn(y-b.y)==0;
	}
};
inline double dot(point a,point b)
{
	return a.x*b.x+a.y*b.y;
}
inline double det(point a,point b)
{
	return a.x*b.y-a.y*b.x;
}
struct line
{// s->e on the left
	point s,e;
	double k;
	line(point a=point(),point b=point())
	{
		s=a;e=b;
		k=atan2(e.y-s.y,e.x-s.x);
	}
	point operator &(const line b)const
    {
        double t=det(b.s-s,b.e-b.s);
		t=t/det(e-s,b.e-b.s);
		return s+t*(e-s);
    }
};

struct lne
{
	double A,B;int ind;
}a[maxl];

int n,cnt;
point res[maxl];
bool in[maxl];
int ans[maxl];

inline bool cmp(const lne &x,const lne &y)
{
	if(sgn(x.A-y.A)==0)
		return x.B>y.B;
	else
		return x.A<y.A;
}

inline void prework()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%lf%lf",&a[i].A,&a[i].B);
		a[i].ind=i;
	}
	sort(a+1,a+1+n,cmp);
}

inline bool onleft(point p,line a)
{
	return sgn(det(p-a.s,a.e-a.s))<0;
}

inline void mainwork()
{
	cnt=0;
	ans[++cnt]=1;res[cnt]=point(0,0);
	for(int i=2;i<=n;i++)
	{
		if(sgn(a[i].A-a[i-1].A)==0) 
			continue;
		line now=line(point(0,a[i].B),point(1,a[i].B+a[i].A));
		while(cnt>=2 && !onleft(res[cnt],now))
			cnt--;
		ans[++cnt]=i;
		res[cnt]=line(point(0,a[ans[cnt-1]].B),point(1,a[ans[cnt-1]].B+a[ans[cnt-1]].A)) & now;
	}
	for(int i=1;i<=cnt;i++)
		in[a[ans[i]].ind]=true;
}

inline void print()
{
	for(int i=1;i<=n;i++)
	if(in[i])
		printf("%d ",i);
}

int main()
{
	prework();
	mainwork();
	print();
	return 0;
}
#include<bits/stdc++.h>
#define maxl 50010
#define eps 1e-8
using namespace std;
 
inline int sgn(double x)
{
    if(x>-eps && x<eps) return 0;
    if(x>0) return 1;
    else    return -1;
}
 
struct point
{
    double x,y;
    point(double a=0,double b=0)
    {
        x=a,y=b;
    }
    point operator + (const point b)const
    {
        return point(x+b.x,y+b.y);
    }
    friend point operator * (const double t,const point p)
    {
        return point(t*p.x,t*p.y);
    }
    point operator - (const point b)const
    {
        return point(x-b.x,y-b.y);
    }
    bool operator == (const point b)const
    {
        return sgn(x-b.x)==0 && sgn(y-b.y)==0;
    }
};
inline double dot(point a,point b)
{
    return a.x*b.x+a.y*b.y;
}
inline double det(point a,point b)
{
    return a.x*b.y-a.y*b.x;
}
struct halfplane
{// s->e on the left
    point s,e;int ind;
    double k,A,B;
    halfplane(point a=point(),point b=point(),int c=0)
    {
        s=a;e=b;ind=c;
        k=atan2(e.y-s.y,e.x-s.x);
    }
    point operator &(const halfplane &b)const
    {
        double t=det(b.s-s,b.e-b.s);
        t=t/det(e-s,b.e-b.s);
        return s+t*(e-s);
    }
}a[maxl];
 
int n,cnt,resn;
point res[maxl*2];
bool in[maxl];
int ans[maxl];
 
inline void prework()
{
    scanf("%d",&n);
    double A,B,inf=1ll<<60;point s,e;
    for(int i=1;i<=n;i++)
    {
        scanf("%lf%lf",&A,&B);
        a[i-1]=halfplane(point(0,B),point(1,B+A),i);
        a[i-1].A=A,a[i-1].B=B;
    }
    //a[n]=halfplane(point(inf,inf),point(-inf,inf),n+1);
    a[n].A=0,a[n].B=inf;
} 
 
inline bool satisfy(point a,const halfplane L)
{
    return sgn(det(a-L.s,L.e-L.s))<0;
}
inline bool HPIcmp(const halfplane &a,const halfplane &b)
{
    if(sgn(a.A-b.A)==0)
        return a.B>b.B;
    else
        return a.A<b.A;
}
halfplane Q[maxl];
void HPI(halfplane line[],int n,point res[],int &resn)
{
    int tot=n;
    sort(line,line+n,HPIcmp);
    tot=1;
    for(int i=1;i<n;i++)
    if(sgn(line[i].A-line[i-1].A)!=0)
        line[tot++]=line[i]; 
    int head=0,tail=1;
    Q[0]=line[0];
    Q[1]=line[1];
    resn=0;
    for(int i=2;i<tot;i++)
    {
        if(sgn(det(Q[tail].e-Q[tail].s,Q[tail-1].e-Q[tail-1].s))==0||
           sgn(det(Q[head].e-Q[head].s,Q[head+1].e-Q[head+1].s))==0)
            return; 
        while(head<tail && !satisfy(Q[tail]&Q[tail-1],line[i]))
            tail--;
        while(head<tail && !satisfy(Q[head]&Q[head+1],line[i]))
            head++;
        Q[++tail]=line[i];
    }
    /*	while(head<tail && !satisfy(Q[tail]&Q[tail-1],Q[head]))
		tail--;
	while(head<tail && !satisfy(Q[head]&Q[head+1],Q[tail]))
		head++;*/
    for(int i=head;i<=tail;i++)
        in[Q[i].ind]=true;
 
}
 
inline void mainwork()
{
    HPI(a,n,res,resn);
}
 
inline void print()
{
    for(int i=1;i<=n;i++)
    if(in[i])
        printf("%d ",i);
}
 
int main()
{
    prework();
    mainwork();
    print();
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值