graham求凸包算法

问题: 点集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


你可能感兴趣的:(graham求凸包算法)