凸包--模板

题目:Surround the Trees

在创建凸包前要对输入的数据进行一定的处理。

首先需要找到所有点左下角的点将它放在数组p[0]的位置。(swap这个函数在c++的标准库中是有的)

左下角这个点一定在凸包上。

View Code
Point tmp;
int pos=0;
tmp.x
=p[0].x; tmp.y=p[0].y;
for (i=1; i<n; i++) //寻找左下角的点
{
if (p[i].y<tmp.y)
{
tmp.x
=p[i].x;
tmp.y
=p[i].y;
pos
=i;
}
if (p[i].y==tmp.y && p[i].x<tmp.x)
{
tmp.x
=p[i].x;
tmp.y
=p[i].y;
pos
=i;
}
}
swap(p[
0], p[pos]);

然后要对所有的点进行排序。

排序的标准是:连接p[i]与p[0](即左下角的点),这条线与x轴形成一个角度a,按照a的大小从小到大排序,如果a相同则按照线段p[i]p[0]的大小从大到小排序。

即p[0]为中心的极角逆时针排序。

排序结果如下图:

View Code
int cmp(const void *a, const void *b) //以左下角的点为基点,其它点与该点的连线与x轴所成的角度,从小到大排序
{
Point p1
=*(Point*)a;
Point p2
=*(Point*)b;
double x=xmult(p[0], p1, p2);
if (x<0) return 1;
if (x==0 && dist(p[0], p1)<dist(p[0], p2)) return 1;
return -1;
}

qsort(
&p[1], n-1, sizeof(p[0]), cmp);

最后就是生成凸包(Graham扫描法)。

result[0]和result[n]这两个表示同一个点,即左下角的那个点。

View Code
void create_convex(int n) //生成凸包
{
result[
0]=p[0];
result[
1]=p[1];
result[
2]=p[2];
int i;
top
=2;
for (i=3; i<=n; i++)
{
while (xmult(result[top-1], result[top], p[i])<=0 && top>=1) top--;
result[
++top]=p[i];
}
}

Graham扫描法凸包的生成过程

posted on 2011-05-01 16:07  tzc_yujunyong  阅读(445)  评论(0)    收藏  举报