Andrew's Monotone Chain二维凸包算法详解:点击打开博客链接
Graham的栈扫描转自:http://www.cnblogs.com/Booble/archive/2011/03/10/1980089.html
Graham的扫描是一个很优美的过程 用到的数据结构也很简单 仅仅是一个栈而已
核心的思想是按照排好的序 依次加入新点得到新的边
如果和上一条边成左转关系就压栈继续 如果右转就弹栈直到和栈顶两点的边成左转关系 压栈继续
实现的时候我们不用存边 只需要含顺序在栈里存点 相邻两点就是一条边
由于我们时时刻刻都保证栈内是一个凸壳 所以最后扫描完毕 就得到了一个凸包
下面还是继续上面的那个样例 演示一下栈扫描的过程
这样Graham扫描算法基本完成
复杂度是排序O(Nlog2N) 扫描O(N) {每个点仅仅出入栈一次}
合起来是一个O(Nlog2N)的算法 很优秀
实现代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int INF=110;
struct Convex
{
int x,y;
}Hull[INF],Res[INF];
bool cmp(Convex a,Convex b)
{
return (a.x<b.x)||(a.x==b.x && a.y<b.y);
}
bool Judge(Convex a,Convex b,Convex c)
{
return (c.x-a.x)*(c.y-b.y)>(c.y-a.y)*(c.x-b.x);
}
int ConvexHull(int len)
{
sort(Hull,Hull+len,cmp);
int m(0);
for(int i=0;i<len;i++)
{
while(m>1 && Judge(Res[m-2],Res[m-1],Hull[i]))
m--;
Res[m++]=Hull[i];
}
int temp=m;
for(int i=len-2;i>=0;i--)
{
while(m>temp && Judge(Res[m-2],Res[m-1],Hull[i]))
m--;
Res[m++]=Hull[i];
}
if(len>1) m--;
return m;
}
void Print(int len)
{
sort(Res,Res+len,cmp);
for(int i=0;i<len;i++)
printf("%d %d\n",Res[i].x,Res[i].y);
}
int main()
{
int ncase;
scanf("%d",&ncase);
while(ncase--)
{
int m;
scanf("%d",&m);
for(int i=0;i<m;i++)
scanf("%d%d",&Hull[i].x,&Hull[i].y);
int temp=ConvexHull(m);
Print(temp);
}
return 0;
}