码迷,mamicode.com
首页 > 其他好文 > 详细

半平面交复习

时间:2020-04-21 10:05:12      阅读:74      评论:0      收藏:0      [点我收藏+]

标签:面积   一段   dig   ring   sort   逆时针   计算几何   abs   入队   

半平面交复习

计算几何易忘点

  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;
    }
    

半平面交复习

标签:面积   一段   dig   ring   sort   逆时针   计算几何   abs   入队   

原文地址:https://www.cnblogs.com/lcyfrog/p/12742090.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!