凸包,在二维平面中可以定义为,一个将所有给出点包含的凸多边形。如下图所示:
而在计算几何中凸包有五种求法:
将所有点两两对应,然后将剩下的(n - 2)个点 一一枚举判断是否在同一侧,如果都在同一侧即这两个点是凸包上的点。
具体的算法实现利用到了叉乘。
如果该式子值大于0,即该点在直线左侧,反之着在直线右侧。
空间复杂度:
时间复杂度:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 7;
typedef long long ll;
typedef unsigned long long ull;
struct Point{
double x,y;
bool ok;
}a[N];
int n;
stack<Point> s;
queue<Point> q;
int cross_product(Point a,Point b,Point c)
{
if(a.x * b.y + a.y * c.x + b.x * c.y - c.x * b.y - b.x * a.y - a.x * c.y > 0) return 1;
else if(a.x * b.y + a.y * c.x + b.x * c.y - c.x * b.y - b.x * a.y - a.x * c.y == 0) return 0;
return -1;
}
void convex_hull()
{
for(int i = 0;i < n;++i)
for(int j = i + 1;j < n;++j){
bool flag = true;
int left = 0,right = 0;
for(int k = 0;k < n;++k){
if(k == i || k == j) ;
else{
if(cross_product(a[i],a[j],a[k]) == 1) left++;
else if(cross_product(a[i],a[j],a[k]) == -1) right++;
if(left && right) {flag = false;break;}
}
}
if(flag) a[i].ok = a[j].ok = true;
}
}
int main()
{
ios::sync_with_stdio(false);
cin >> n;
for(int i = 0;i < n;++i){
cin >> a[i].x >> a[i].y;
a[i].ok = false;
}
convex_hull();
for(int i = 0;i < n;++i)
if(a[i].ok) cout << a[i].x << ' ' << a[i].y << endl;
return 0;
}
先将所有的点按照纵坐标优先的方式排序,显然纵坐标最小的点会在凸包上,所以从纵坐标最小的点开始入栈0,按逆时针方向搜索,将角度最小的点压入栈,然后重复操作。
空间复杂度:
时间复杂度: