参考文 《矢量的凸包应用》
这里专讲代码。
求向量乘法代码
inline int con(node a, node b, node c) {
return (c.x-a.x)*(b.y-a.y)-(c.y-a.y)*(b.x-a.x);
}
其实也是蛮好记的。
求两点距离
inline double dis(node a, node b) {
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
向量乘法参与运算时,要记得右手法则。
拇指表示正负,其他四指表示旋转方向。
根据刚刚的向量积,可以推导得到,如果
a
b
→
\overrightarrow{ab}
ab在
a
c
→
\overrightarrow{ac}
ac的逆时针方向,那么
a
b
→
×
a
c
→
<
0
\overrightarrow{ab}\times\overrightarrow{ac}<0
ab×ac<0
如果是顺时针那么
a
b
→
×
a
c
→
>
0
\overrightarrow{ab}\times\overrightarrow{ac}>0
ab×ac>0
如果共线则
a
b
→
×
a
c
→
=
0
\overrightarrow{ab}\times\overrightarrow{ac}=0
ab×ac=0
——《矢量的凸包应用》
于是非常容易得出比较函数
inline bool cmp(node b, node c) {
int ans=con(a[1], b, c);
if(ans) return ans>0;//bxc>0,则b在c顺时针方向
return dis(b, a[1])<dis(c, a[0]);
}
来看主函数
求开始点
for(int i=1; i<=n; i++) {
scanf("%d%d", &a[i].x, &a[i].y);
if(a[mix].y>a[i].y||(a[mix].y==a[i].y&&a[mix].x>a[i].x)) mix=i;//求出第一个点
}
排序
swap(a[1], a[mix]);
sort(a+2, a+n+1, cmp);//排序
栈操作
for(int i=3; i<=n; i++) {
while(top&&con(st[top-1], a[i], st[top])>=0) {
top--;//上一个点不对
}
st[++top]=a[i];
}
赠品:求凸多边形面积
int ans=0;
for(int i=0; i<=top; i++) {
ans+=(st[(i+1)%(top+1)].x*st[i].y-st[(i+1)%(top+1)].y*st[i].x)/2;
}