半平面交复习
Posted lcyfrog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了半平面交复习相关的知识,希望对你有一定的参考价值。
半平面交复习
计算几何易忘点
-
叉积
a到b顺时针则为正,逆时针则为负(把a顺时针方向转到b的方向,夹角为 θ。当 0≤θ<π时值为正;当π≤θ<2π时值为负。
-
极角排序
atan2 返回((-pi),(pi)),值等于arctan
-
直线交点
用一条直线的起点+一段向量,用面积比求比例,画两条线段手推
算法过程
-
确定左半平面还是右半平面(最好写左半平面)
-
排序函数,先按斜率排序,否则靠近可行域的在前面
-
每次加入新直线,去掉交点在要求的一侧的异侧(右边)的那个直线,前后都要去,可以存交点
-
最后用队头去一下队尾
-
代码实现
#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; }
以上是关于半平面交复习的主要内容,如果未能解决你的问题,请参考以下文章