• 半平面交复习


    半平面交复习

    计算几何易忘点

    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;
      }
      
  • 相关阅读:
    2.java基础语法(上)
    1.java概述
    Qt layout透明的问题
    Duilib 关于ChildLayout崩溃的问题
    关于注册表使用的几个问题
    win32接口获取ping值
    Web开发中遇到的问题
    DuiLib 窗口透明方法
    通过进程名杀死进程的方法--WIN32
    关于在Qt的MainWindow窗口中添加Layout的问题
  • 原文地址:https://www.cnblogs.com/lcyfrog/p/12742090.html
Copyright © 2020-2023  润新知