判断是否是整数:fabs(x – (int)x) > eps
double精度1e9,long double精度1e18
实数比较:
eps为精度,sign返回正负,cmp返回大小
typedef double db;
const db eps=1e-6;
const db pi=acos(-1);
int sign(db k){
if (k>eps) return 1; else if (k<-eps) return -1; return 0;
}
int cmp(db k1,db k2){return sign(k1-k2);}
点:
struct point{
db x,y;
point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};}
point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};}
point operator * (db k1) const{return (point){x*k1,y*k1};}
point operator / (db k1) const{return (point){x/k1,y/k1};}
int operator == (const point &k1) const{return cmp(x,k1.x)==0&&cmp(y,k1.y)==0;}
// 逆时针旋转
point turn(db k1){return (point){x*cos(k1)-y*sin(k1),x*sin(k1)+y*cos(k1)};}
point turn90(){return (point){-y,x};}
bool operator < (const point k1) const{
int a=cmp(x,k1.x);
if (a==-1) return 1; else if (a==1) return 0; else return cmp(y,k1.y)==-1;
}
db abs(){return sqrt(x*x+y*y);}
db abs2(){return x*x+y*y;}
db dis(point k1){return ((*this)-k1).abs();}
//返回向量的单位向量
point unit(){db w=abs(); return (point){x/w,y/w};}
void scan(){double k1,k2; scanf("%lf%lf",&k1,&k2); x=k1; y=k2;}
void print(){printf("%.11lf %.11lf\n",x,y);}
//返回极角(弧度)
db getw(){return atan2(y,x);}
//返回原点对称点
point getdel(){if (sign(x)==-1||(sign(x)==0&&sign(y)==-1)) return (*this)*(-1); else return (*this);}
//返回半区
int getP() const{return sign(y)==1||(sign(y)==0&&sign(x)==-1);}
};
点积叉积:
这里默认起点是原点,非原点请平移
db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;}
db dot(point k1,point k2){return k1.x*k2.x+k1.y*k2.y;}
极角排序:
先分上下半区,然后用叉积判断大小。
旋转:
1、用旋转矩阵把点转换成旋转之后的点
[
c
o
s
α
−
s
i
n
α
c
o
s
α
s
i
n
α
]
⋅
[
x
y
]
\begin{bmatrix} cos\alpha&-sin\alpha\\ cos\alpha&sin\alpha\\ \end{bmatrix} · \begin{bmatrix} x\\ y\\ \end{bmatrix}
[cosαcosα−sinαsinα]⋅[xy]
2、用复数相乘,因为复数相乘的结果就是模相乘,辐角相加,所以乘上一个角度为α的单位向量就可以了
(
x
+
y
⋅
i
)
⋅
(
c
o
s
α
+
s
i
n
α
⋅
i
)
(x + y·i) · (cos\alpha + sin\alpha·i)
(x+y⋅i)⋅(cosα+sinα⋅i)
结果就是:
直线交点:
先判断是否平行再求交点
int checkLL(point k1,point k2,point k3,point k4){
return cmp(cross(k3-k1,k4-k1),cross(k3-k2,k4-k2))!=0;
}
point getLL(point k1,point k2,point k3,point k4){
db w1=cross(k1-k3,k4-k3),w2=cross(k4-k3,k2-k3);
return (k1*w2+k2*w1)/(w1+w2);
}
点集直径(最远点对):
有一个旋转卡壳的方法,不知道这个是不是
旋转卡壳:两条平行线卡住凸包,下一个卡住的点通过叉积判断,绕一圈就完事了
db convexDiameter(vector<point>A){
int now=0,n=A.size(); db ans=0;
for (int i=0;i<A.size();i++){
now=max(now,i);
while (1){
db k1=A[i].dis(A[now%n]),k2=A[i].dis(A[(now+1)%n]);
ans=max(ans,max(k1,k2)); if (k2>k1) now++; else break;
}
}
return ans;
}
还有很多东西遇到再说吧