OI计算几何 简单学习笔记
学习平面几何,首先我们要会熟练地应用向量,其次也要知道一些基本的几何知识。(其实看看数学课本就可以了吧)
因为是看的蓝书,所以很多东西做了引用。(update:还参考了赵和旭dalao的讲义)
下面先介绍一些常用的操作:
点的定义
struct point
{
double x,y;
point(double x=0,double y=0):x(x),y(y){}
};
向量的定义
typedef point vec
值的判断
inline int dcmp(double x)
{
if(fabs(x)<eps) return 0;
else if(x<0.0) return -1;
else return 1;
}
向量的基本运算
vec operator + (vec a,vec b){return vec(a.x+b.x,a.y+b.y);}
vec operator - (vec a,vec b){return vec(a.x-b.x,a.y-b.y);}
vec operator * (vec a,double b){return vec(a.x*b,a.y*b);}
vec operator / (vec a,double b){return vec(a.x/b,a.y/b);}
向量的点积
这个学过高中数学必修四的应该都知道。
比如说对于\(\vec a\)和\(\vec b\),集合上的定义为:\(\vec a\times \vec b\times cos \theta\) ,代数的计算方法则为\(ax*bx+ay*by\)。
inline double dot(vec a,vec b){return a.x*b.x+a.y*b.y;}
向量的长度
inline double length(vec a){return sqrt(dot(a,a));}
向量的夹角(返回值为弧度制)
inline double angle(vec a,vec b){return acos(dot(a,b)/length(a)/length(b));}
向量的叉积
对于\(\vec a\)和\(\vec b\),集合上的定义为:\(\vec a\times \vec b\times sin \theta\) ,代数的计算方法则为\(ax*by-ay*bx\)。
它的几何意义表示这两个向量形成的平行四边形的面积。
inline double cross(vec a,vec b){return a.x*b.y-a.y*b.x;}
因为叉积在数值上可以表示向量a,b围成的平行四边形的面积,所以我们可以通过叉积来计算三个点围成的三角形的面积——
inline double area(point a,point b,point c){return cross(b-a,c-a);}
除此之外还有一些应用:
向量的旋转(注意是逆时针旋转)
公式为\(x_{new}=xcosa-ysina\),\(y_{new}=xsina+ycosa\),其中a为逆时针旋转的角的弧度值。
inline vec rotate(vec x,double a)
{return vec(x.x*cos(a)-x.y*sin(a),x.x*sin(a)+x.y*cos(a));}
直线的交点
inline point getline_intersection(point p,vec v,point q,vec w)
{
vec u=p-q;
double t=cross(w,u)/cross(v,w);
return p+mul(v,t);
}
点到直线的距离
其实数学上有个公式叫做\(\frac{fabs(ax+by+c)}{\sqrt {k^2+1}}\),但是这个需要直线的表达式,我们可以利用叉积来更方便地进行计算。( 也就是用平行四边形的面积除以底)
inline double distance(point p,point a,point b)//a,b组成的是边
{
vec v1=b-a,v2=p-a;
return fabs(cross(v1,v2))/length(v1);//如果不取绝对值,得到的是有向距离
}
多边形的计算(同时适用于凸多边形,凹多边形)
其实就是从一个顶点开始,将多边形划分成若干个三角形进行计算。(从p0开始划分)
inline double Area(point* p,int n)
{
double cur_area=0
for(int i=1;i<n-1;i++)
cur_area+=cross(p[i]-p[0],p[i+1]-p[0]);
return cur_area/2;
}
线段相交判定
inline bool whether_intersection(point a1,point a2,point b1,point b2)
{
double c1=cross(a2-a1,b1-a1);
double c2=cross(a2-a1,b2-a1);
double c3=cross(b2-b1,a2-b1);
double c4=cross(b2-b1,a1-b1);
return (dcmp(c1)*dcmp(c2)<0)&&(dcmp(c3)*dcmp(c4)<0);
}
多边形的重心
把一个多边形剖分成很多的三角形,依次给每个三角形求重心,按照面积加权求平均就是该多边形的重心。
判断一个点是否在多边形内
从该点随便引(一般都是竖直吧qwq)一条射线,计算它与多边形所有边的交点的数目,如果是奇数个就在多边形内,如果是偶数个就在多边形外。(在线段的两端点上相交不算有交点)
但是要注意一下细节
求两圆的交点
求两圆的内(外)公切线
如果一条直线和两个圆都相切,这条直线叫做两个圆的公切线。如果两圆在公切线的同侧,称这条公切线为两圆的外公切线,如果两圆分别在公切线的两侧,称这条公切线为两圆的内公切线。
求凸包
懒得省事了,直接放一个模板好了qwqwq
inline bool cmp(struct Node a,struct Node b)
{
double A=atan2((a.y-t[1].y),(a.x-t[1].x));
double B=atan2((b.y-t[1].y),(b.x-t[1].x));
if(A!=B) return A<B;
else return a.x<b.x;
}
inline double cross(Node a,Node b,Node c){return (a.x-c.x)*(b.y-c.y)-(a.y-c.y)*(b.x-c.x);}
inline void solve()
{
t[0]=(Node){0x3f3f3f3f,0x3f3f3f3f};
int k=0;
for(int i=1;i<=n;i++)
if(t[i].y<t[0].y||(t[i].y==t[0].y&&t[i].x<t[0].x))
t[0]=t[i],k=i;
swap(t[1],t[k]);
sort(&t[2],&t[1+n],cmp);
s[0]=t[1],s[1]=t[2];
top=1;
for(int i=3;i<=n;i++)
{
while(top&&cross(s[top-1],t[i],s[top])>=0.0) top--;
s[++top]=t[i];
}
}
动态凸包:(请看我的这篇博客)
关键代码:(我这里使用的是极角排序)
inline void solve(Node x)
{
nxt=st.lower_bound(x);
if(nxt==st.end()) nxt=st.begin();
pre=get_pre(nxt);
if(cross((*nxt)-(*pre),x-(*pre))>=0) return;
cur_ans-=get_len((*nxt)-(*pre));
cur_ans+=get_len(x-(*nxt))+get_len(x-(*pre));
st.insert(x);
tmp=get_pre(pre);
while(cross(x-(*pre),(*pre)-(*tmp))>=0)
{
cur_ans-=get_len(x-(*pre))+get_len((*pre)-(*tmp));
cur_ans+=get_len(x-(*tmp));
st.erase(pre);
pre=tmp;
tmp=get_pre(pre);
}
tmp=get_nxt(nxt);
while(cross(x-(*nxt),(*nxt)-(*tmp))<=0)
{
cur_ans-=get_len(x-(*nxt))+get_len((*nxt)-(*tmp));
cur_ans+=get_len(x-(*tmp));
st.erase(nxt);
nxt=tmp;
tmp=get_nxt(nxt);
}
return;
}
点在多边形内的判定
method1 射线法
就是从某一个判定点出发,任意引出一条射线。如果和边界相交奇数次,说明点在多边形内。如果相交偶数次,说明点在多边形外。注意射线如果在端点处和多边形相交,或者穿过一条完整的边,则需要重新引出一条射线QAQ
method2 转角法
我们把多边形的每条边的转角加起来,如果是360度,说明在多边形内。如果是0度,说明在多边形外。如果是180度,说明在多边形的边界上。优化的操作如下:假想有一条向右的射线,统计多边形穿过这条射线正反多少次,把这个数基座绕数,逆时针穿过时+1,顺时针穿过时-1.
旋转卡壳
半平面交
咕咕咕
OI计算几何 简单学习笔记的更多相关文章
- OI数学 简单学习笔记
基本上只是整理了一下框架,具体的学习给出了个人认为比较好的博客的链接. PART1 数论部分 最大公约数 对于正整数x,y,最大的能同时整除它们的数称为最大公约数 常用的:\(lcm(x,y)=xy\ ...
- OI图论 简单学习笔记
网络流另开了一个专题,所以在这里就不详细叙述了. 图 一般表示为\(G=(V,E)\),V表示点集,E表示边集 定义图G为简单图,当且仅当图G没有重边和自环. 对于图G=(V,E)和图G2=(V2,E ...
- OI网络流 简单学习笔记
持续更新! 基本上只是整理了一下框架,具体的学习给出了个人认为比较好的博客的链接. ..怎么说呢,最基础的模板我就我不说了吧qwq,具体可以参考一下这位大佬写的博客:最大流,最小割,费用流 费用流 跑 ...
- OI多项式 简单学习笔记
咕咕咕 先开个坑(其实是存模板来了) 一些特别简单的前置东西qwq 复数的计算 复数相加:向量相加,复数相乘.复数相乘:模长相乘,旋转量相加(就是复平面坐标轴逆时针旋转的角度) (当然也可以直接使用c ...
- OI字符串 简单学习笔记
持续更新qwq KMP 其实是MP啦qwq 就是先自己匹配自己得到状态图,然后再在上面进行模式串的匹配. nxt数组返回的是以该节点结尾的,最长的,在前面出现过的,不相交的,字符串的最靠右的,末位位置 ...
- Log4j简单学习笔记
log4j结构图: 结构图展现出了log4j的主结构.logger:表示记录器,即数据来源:appender:输出源,即输出方式(如:控制台.文件...)layout:输出布局 Logger机滤器:常 ...
- Linux——帮助命令简单学习笔记
Linux帮助命令简单学习笔记: 一: 命令名称:man 命令英文原意:manual 命令所在路径:/usr/bin/man 执行权限:所有用户 语法:man [命令或配置文件] 功能描述:获得帮助信 ...
- <<C++标准程序库>>中的STL简单学习笔记
0. 内容为个人学习笔记, 仅供参考, 如有错漏, 欢迎指正! 1. STL中的所有组件都是由模板构成的, 所以其元素可以是任意型别的. 组件有: - 容器: 管理某类对象的集合. 不同的容器有各自的 ...
- OI动态规划&&优化 简单学习笔记
持续更新!! DP的难点主要分为两类,一类以状态设计为难点,一类以转移的优化为难点. DP的类型 序列DP [例题]BZOJ2298 problem a 数位DP 常用来统计或者查找一个区间满足条件的 ...
随机推荐
- Mysql 性能优化 ( my.cnf )
简介: Mysql 参数优化 一.Mysql 源码编译参数 shell > yum -y install gcc gcc-c++ make cmake ncurses-devel zlib-de ...
- sqlserver,oracle,mysql等的driver驱动,url怎么写
oracle driver="oracle.jdbc.driver.OracleDriver" url="jdbc:oracle:thin:@localhost:1521 ...
- 获取崩溃时的调用栈和生成dump文件,然后自动重启
首先要说明的是: linux 下 比较方便可以得到 崩溃时的调用栈,win下 比较难办 1. linux 获取调用栈 代码奉上: #include <execinfo.h> //在头 ...
- Android开发实战之ViewPager的轮播
在安卓开发的许多控件中,如果你没有使用过ViewPager,就不能算是一个安卓开发工程师,在本篇博文中,我会总结ViewPager的使用方法, 以及一些开发中的拓展.希望本篇博文对你的学习和工作有所帮 ...
- NoSuchBeanDefinitionException:No qualifying bean of type found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency.
报错如下: NoSuchBeanDefinitionException:No qualifying bean of type found for dependency: expected at l ...
- Vue+WebPack游戏设计:自动背景贴图和游戏主循环的实现
- fidder 自动保存请求内容
背景: 因为公司有有app和sdk,这些项目没有对应的接口统计.重构的时候很容易忽略掉.所以对fiddler写了一点代码,能将请求的数据写入到文件或者数据库中.方便统计接口,下次重构的时候,方便统计影 ...
- Unity几个有用的游戏运动特效
本文摘要 本文主要记录了我在开发格斗游戏时用到的几个运动特效,可以方便地表现武器挥动.运动模糊和其他一些特效.灵活使用可以大幅提升格斗游戏的视觉效果和感染力.有关Unity的其他话题也可以查阅我的其他 ...
- spring4-4-jdbc-01
1.建立数据属性文件db.properties jdbc.user=root jdbc.password=root jdbc.driverClass=com.mysql.jdbc.Driver jdb ...
- Ubuntu命令行下安装、卸载、管理软件包的方法
一.Ubuntu中软件安装方法 1.APT方式 (1)普通安装:apt-get install softname1 softname2 -; (2)修复安装:apt-get -f install so ...