凸包:用一个凸多边形将所有点围起来,这个凸多边形就是凸包
1.先要引入一个数学工具,向量叉积
|c|=|a×b|=|a| |b|sinα (α为a,b向量之间的夹角)
则 |c| 为向量a ,b所组成的平行四边形的面积
这里是用叉积判断两向量的相对位置关系(非常有用!)
则 a x b < 0 (a在b的逆时针方向 ) , b x a > 0(b在a的顺时针方向)
//求叉积
struct node{
double x ,y;
node operator -( const node & s ){
return {x-s.x , y-s.y};
}
}p[N] ,s[N];
inline double X( node a ,node b ){
return a.x*b.y - b.x*a.y;
}
2. Graham扫描法求凸包
1)找出所有点中在最左下角的点定为极点
//找左下边界点
int k = 1;
rep( i ,2 ,n ){
if( p[i].y < p[k].y || p[i].y == p[k].y && p[i].x < p[k].x )
k = i;
}
swap( p[1] ,p[k] );
2)利用叉积进行极角排序
//极角比较
bool cmp ( node &a , node &b ){
double x = X(a-p[1] ,b-p[1]);
//叉积判断向量位置关系
if( x > 0 )return 1;
if( x==0 && dis( a ,p[1])1]) )return 1;
return 0;
}
//极角排序
sort( p+2 ,p+n+1 ,cmp);
3)存凸包
s为存凸包的栈 ,t为栈顶
则由以下关系用叉积取舍s中的点
//将凸包存在s中
s[1] = p[1];
s[2] = p[2];
int t = 2;
rep( i ,3 ,n ){
while( t >= 2 && mul( s[t-1] ,s[t] ,p[i] )<=0 )t--;
s[++t] = p[i];
}
然后凸包就求出来了
模板题 :
P2742 【模板】二维凸包 / [USACO5.1]圈奶牛
#include
#include
#include
#include
#include <set>
#include
#include
#include <string>
#include
#include
#include