半平面交复习

Posted lcyfrog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了半平面交复习相关的知识,希望对你有一定的参考价值。

半平面交复习

计算几何易忘点

  1. 叉积

    a到b顺时针则为正,逆时针则为负(把a顺时针方向转到b的方向,夹角为 θ。当 0≤θ<π时值为正;当π≤θ<2π时值为负。

  2. 极角排序

    atan2 返回((-pi),(pi)),值等于arctan

  3. 直线交点

    用一条直线的起点+一段向量,用面积比求比例,画两条线段手推

算法过程

  1. 确定左半平面还是右半平面(最好写左半平面)

  2. 排序函数,先按斜率排序,否则靠近可行域的在前面

  3. 每次加入新直线,去掉交点在要求的一侧的异侧(右边)的那个直线,前后都要去,可以存交点

  4. 最后用队头去一下队尾

  5. 代码实现

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    int read(){
    	int x=0,pos=1;char ch=getchar();
    	for(;!isdigit(ch);ch=getchar()) if(ch==‘-‘) pos=0;
    	for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+ch-‘0‘;
    	return pos?x:-x;
    }
    const int N = 3e5+500;
    #define db double
    const double eps= 1e-15;
    const db inf = 1e18;
    using namespace std;
    struct point{
    	db x,y;
    	point (double x=0,double y=0): x(x),y(y){}
    	db operator *(point b){
    		return x*b.y-y*b.x;
    	}
    	db operator ^(point b){
    		return x*b.x+y*b.y;
    	}
    	point operator -(point b){
    		return point(x-b.x,y-b.y);
    	}
    	point operator +(point b){
    		return point(x+b.x,y+b.y);
    	}
    	point operator *(db b){
    		return point (x*b,y*b);
    	}
    	db dis(){
    		return sqrt(x*x+y*y);
    	}
    }p[N],t[N];
    int comp0(db x){
    	return fabs(x)<=eps?0:(x>0?1:-1);
    }
    struct line{
    	point p,v;
    	line(point p=point(0,0),point v=point(0,0)) :p(p),v(v){}
    	double k;
    	void getk(){
    		k=atan2((v.y-p.y),(v.x-p.x));//y/x
    	}
    	const int operator <(line y)const{
    		return comp0(k-y.k)==0?((y.p-p)*(y.v-p)>-eps):(k<y.k);斜率/位置*
    	}
    }s[N],q[N];
    int n,top;
    point inter(line a,line b){
    	point v1=a.v-a.p,v2=b.v-b.p;
    	return b.p+v2*(((b.p-a.p)*v1)/(v1*v2));//面积比例法
    }
    void work(){
    	sort(s+1,s+top+1);
    	int r=0,l=1;
    	for(int i=1;i<=top;i++){
    		if(comp0(s[i].k-s[i-1].k)){//入斜率一样就跳过,排序一定要排好
    			while(l<r&&(s[i].v-t[r])*(s[i].p-t[r])>eps) r--;//先从后面去掉一些直线
    			while(l<r&&(s[i].v-t[l+1])*(s[i].p-t[l+1])>eps) l++;//再从前面限制
    			q[++r]=s[i];//加入队尾
    			if(l<r) t[r]=inter(q[r],q[r-1]);//求交点
    		}
    	}
    	while(r>l&&(q[l].v-t[r])*(q[l].p-t[r])>eps) r--;
    	t[r+1]=inter(q[r],q[l]);r++;//记得最后一条边和第一条边有交点
    	return 0;
    }
    

以上是关于半平面交复习的主要内容,如果未能解决你的问题,请参考以下文章

半平面交模板 HDU 1469

半平面交

半平面交

半平面交

BZOJ 1038 ZJOI2008 瞭望塔 半平面交

poj 3384 半平面交