在ACM计算几何中,我们常常重复用到许多方法,例如求点距,求直线方程,等等。不妨利用模板总结之。这些模板为我从网上学习后加入自己的理解糅合得来qwq,看了很多的博客,查了很多书籍,其中印象最深的是林夕林夕关于计算几何模板的总结,大家也可以去参考他的应该比我的更详细qwq
(不过大佬最近好像出没比较少了)
所以我这个主要还是留着自己参考吧,能帮到他人再好不过了
为了不产生歧义,方便理解,本模板使用笛卡尔坐标系,封装的多是数学中常见的函数。
前置知识:高中数学,向量外积相关
模板仅供参考学习,不保证任何情况下不会因为误差WA掉或是RE掉
基础声明
首先,打acm的时候double这个数据类型就比较恶心(容易浮动导致误差),而计算几何中各种计算又几乎没法单独用整型解决。因此我们需要一个小常数来判断误差。
例如,计算啥啥面积的时候,我们需求误差在10的-6次方以内,那么就可以定义这个常数为10的-6次方:
const double eps = 1e-6;
然后,我们的目标是,当误差小于1e-6时,误差将被忽略不计。也就是说,两个数比较时,差距在1e-6以内,我们就可以认为这两个数相等。
一般的计算中,本来两个相等的数字,因为我们计算路径的不同,浮点数就可能会发生不同的浮动,导致 = = == ==运算符检查本来应该相等的两个浮点数时返回了0。这时我们就可以用误差来避免了。
以下为重载大小判断的函数:
int cmp(const double& a, const double& b)
{
if(fabs(a - b) < eps) return 0; // 若误差范围内相等,返回0
else if(a > b) return 1; // 若a > b,返回1
return -1; // 若a < b,返回-1
}
另外还有计算几何中常用的常量:
const double pi = 3.1415927536;
const double INF = 1e100;
浮点数的表数范围巨大,可以表示到10的200多次方,但是实际上几十次方浮动误差就大到难以接受了……因此,我们可以用一个100次方表示无穷大,反正它够大就对了,但是却不能直接拿来做计算(总之就是误差非常大)。
另外,我们也常用C++内置的反三角函数acos()
来求角度。但是这个函数有个问题,我们都知道反余弦函数的定义域是 [ − 1 , 1 ] [-1,1] [−1,1],然而由于浮点数的浮动偏移,我们得到的1很可能实际上是1.00001,1.0000001这种数,这些数据不在反余弦函数的定义域内了,那么把它们作为参数传进去就没法计算,就会导致Runtime Error,就没法AC!QAQ!所以我们可以把acos()
函数二次包装一下,打消这个顾虑。
double acs(double x)
{
if(x > 1) x = 1;
else if(x < -1) x = -1;
return acos(x);
}
顺便把反正弦函数也包装一下
double asn(double x)
{
if(x > 1) x = 1;
else if(x < -1) x = -1;
return asin(x)