问题: 点集Q的凸包(convex hull)是指一个最小凸多边形,满足Q中的点或者在多边形边上或者在其内。
这个算法是由数学大师葛立恒Graham发明的,他曾经是美国数学学会AMS主席、ATT 首席科学家... (see http://www.doc88.com/p-08332037489.html)
模板:see http://kmplayer.iteye.com/blog/604405
#include <iostream>
#include <algorithm>
using namespace std;
class point
{
public:
double x, y;
point(){x = 0; y = 0;}
};
bool mult(point sp, point ep, point op)
{
cout << "checking (" << sp.x << "," << sp.y <<"),(" << ep.x << "," << ep.y << "),(" << op.x << "," << op.y<<") : " ;
bool tu = (sp.x - op.x)*(ep.y - op.y) >= (ep.x - op.x)*(sp.y - op.y);
cout << tu << endl;
return tu;
}
bool operator<(const point &l, const point &r)
{
return l.y < r.y || ((l.y == r.y) && (l.x < r.x));
}
void print(point res[], int n)
{
cout << "stack : " ;
for(int i = 0; i <= n; i++)
{
cout << "(" << res[i].x << ", " << res[i].y << "),";
}
cout << endl;
}
int graham(point pnt[], int n, point res[])
{
int i, len, k = 0, top = 1;
sort(pnt, pnt + n);
if (n == 0)
{
return 0;
}
res[0] = pnt[0];
if (n == 1)
{
return 1;
}
res[1] = pnt[1];
if (n == 2)
{
return 2;
}
res[2] = pnt[2];
for(int i = 2; i < n; i++)
{
while(top && mult(pnt[i], res[top], res[top-1]))
{
cout << "poping point (" << res[top].x << ", " << res[top].y << ")" << endl;
top --;
print(res, top);
}
cout << "pusing point (" << pnt[i].x << ", " << pnt[i].y << ")" << endl;
res[++top] = pnt[i];
print(res, top);
}
print(res, top);
cout << "-----" << endl;
len = top;
res[++top] = pnt[n-2];
print(res, top);
for(i = n-3; i>=0; i--)
{
while(top != len && mult(pnt[i], res[top], res[top-1]))
{
cout << "poping point (" << res[top].x << ", " << res[top].y << ")" << endl;
top--;
print(res, top);
}
cout << "pusing point (" << pnt[i].x << ", " << pnt[i].y << ")" << endl;
res[++top] = pnt[i];
print(res, top);
}
return top;
}
point pnt[1000];
point res[1000];
int n = 0;
int main()
{
double x,y;
while(cin >> x >> y)
{
pnt[n].x = x;
pnt[n].y = y;
n++;
}
int num = graham(pnt, n, res);
print(res, num);
}
测试结果:
/home/a/j/nomad2:cat input
1 1
2 2
3 2.5
4 1
/home/a/j/nomad2:cat input |./a.out
checking (2,2),(4,1),(1,1) : 0
pusing point (2, 2)
stack : (1, 1),(4, 1),(2, 2),
checking (3,2.5),(2,2),(4,1) : 1
poping point (2, 2)
stack : (1, 1),(4, 1),
checking (3,2.5),(4,1),(1,1) : 0
pusing point (3, 2.5)
stack : (1, 1),(4, 1),(3, 2.5),
stack : (1, 1),(4, 1),(3, 2.5),
-----
stack : (1, 1),(4, 1),(3, 2.5),(2, 2),
checking (4,1),(2,2),(3,2.5) : 0
pusing point (4, 1)
stack : (1, 1),(4, 1),(3, 2.5),(2, 2),(4, 1),
checking (1,1),(4,1),(2,2) : 1
poping point (4, 1)
stack : (1, 1),(4, 1),(3, 2.5),(2, 2),
checking (1,1),(2,2),(3,2.5) : 0
pusing point (1, 1)
stack : (1, 1),(4, 1),(3, 2.5),(2, 2),(1, 1),
stack : (1, 1),(4, 1),(3, 2.5),(2, 2),(1, 1),
说明: 算法的复杂度为sort的复杂度O(NlogN),后面的扫描为O(N)。
POJ 1113