今天学弟问到了…就稍稍写一下吧,似乎是叫(Graham扫描法)?
(只会这一个) 太菜了
其实求凸包很简单 (为什么当时就是学不会?被自己菜哭)
首先要找到左下角的点.(它一定是凸包上的点)
以那个点为中心极角排序
然后把排完序的前两个点入栈
判断栈中倒数第二个点与最后一个点和当前判断的点构成向量的叉乘,如果为负值,退栈,一直退到不为负值或者栈中的元素树小于2
把正在判断的点入栈
等到所有点遍历完了,栈中的元素就是凸包上的点…
代码如下:(实在没有什么值得多说的…)
#include <iostream>
#include <algorithm>
#define MAX 1000
using namespace std;
struct node {
int x, y;
node(int _x = 0, int _y = 0)
{
x = _x;
y = _y;
}
node operator -(node a)//向量减
{
return node(x - a.x, y - a.y);
}
int operator*(node a)//叉乘
{
return (x * a.y - y * a.x);
}
friend int getdis(node a, node b)//两点间距离的平方
{
return ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
void show()
{
cout << "x:" << x << " y:" << y << endl;
}
}p[MAX];
int ans[MAX];
int n;
int cmp(node a, node b)//极角排序
{
int t = (a - p[0]) * (b - p[0]);
if (t != 0)
return t > 0;
else
return getdis(a, p[0]) < getdis(b, p[0]);
}
void getans()
{
int len = 0;
ans[len++] = 0;
for (int i = 1; i < n; i++)
{
while (len >= 2 && ((p[ans[len - 1]] - p[ans[len - 2]]) * (p[i] - p[ans[len - 2]]) <= 0)) len--;
ans[len++] = i;
}//求凸包...
for (int i = 0; i < len; i++)
p[ans[i]].show();
int s = 0;
for (int i = 1; i+1 < len; i++)
{
s += (p[ans[i]] - p[0]) * (p[ans[i + 1]] - p[0]);
}//求凸多边形面积(因为我这里都是整数,就没用double...正常写肯定要用double的...)
cout << 1.0 * s / 2;
}
int main()
{
cin >> n;
for (int i = 0; i < n; i++)
cin >> p[i].x >> p[i].y;
int m = 0;//最左下的点的下标
for (int i = 1; i < n; i++)
{
if (p[i].y < p[m].y)
m = i;
else if (p[i].y == p[m].y && p[i].x < p[m].x)
m = i;
}
node t = p[m];
p[m] = p[0];
p[0] = t;//一定要把最左下的点和最开始的点换位置!!这里处理不好还会出莫名其妙的BUG(不知道为什么,对sort研究不深...)
sort(p, p + n, cmp);
getans();
return 0;
}
/*
9
1 0
3 2
2 0
2 1
2 2
2 3
1 1
0 0
3 3
*/