凸包问题 —— 两种算法
第一种算法:Graham_scan算法
这个算法还蛮好理解的,下面这篇文章对一些基本的凸包所涉及的几何概念进行了解释,另外还附上了代码,挺好的,链一下
除此之外,我在做题(也就是hdu4946)时发现了一个很严肃的问题...它揭示了graham_scan用极坐标排序时导致的问题。
链接如下:共线凸包 极坐标排序和水平排序的抉择
附模板:
#include
#include
#define maxn 100
int top;//凸包的顶点个数
typedef struct point
{
int x,y;
}point;
point p[maxn] , stack[maxn] ;
int max(int a,int b)
{
return a>b?a:b;
}
int dis(point p1,point p2)///两点的距离的平方
{
return (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y);
}
///叉积,结果小于表示向量p0p1的极角大于p0p2的极角,等于则两向量共线
int multi(point p1, point p2, point p0)
{
return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
}
///按极角排序,dis(a,p[0])
1&&multi(p[i],stack[top],stack[top-1])>=0)///如果取等于号的话,共线的都会被枪毙哦
top--;
stack[++top]=p[i];
}/**the last point is the first point*/
}
int main()
{
int n , i ;
while( scanf("%d",&n)!=EOF ) {
for(i=0;i
< n ++ ){ "x:%d y;%d\n" p[i].x p[i].y "the points on tubao:\n" i<="top" i++ stack[i].x stack[i].y return 0; code>
第二种算法:Andrew算法
这个算法用的就是水平排序,具体的情况,我也直接给链接,链接的模板好像是刘汝佳的,打的还蛮好的,他就可以考虑共线点的问题,但是那个判断的时候是小于还是小于等于神马的,要自己注意
附模板:
#include
#include
#include
#include
#include
#include
using namespace std; const double eps = 1e-8,Pi=3.14159265; int n; inline int dcmp(double x)//三态函数 { if(fabs(x) < eps) return 0; else return x>0 ? 1 : -1; } #define Vector Point struct Point { double x,y; inline Point(double x=0,double y=0):x(x),y(y) {} }p[10000+5],ch[10000+5]; bool myCmp(Point A, Point B) { if(A.x != B.x) return A.x < B.x; else return A.y < B.y; } Vector operator + (Vector A, Vector B) {return Vector(A.x + B.x, A.y + B.y);} Vector operator - (Vector A, Vector B) {return Vector(A.x - B.x, A.y - B.y);} bool operator == (const Vector& A, const Vector& B) {return dcmp(A.x-B.x)==0 && dcmp(A.y-B.y)==0;} inline double Cross(Vector A, Vector B)//叉积 { return A.x * B.y - A.y * B.x; } int ConvexHull() { sort(p,p+n,myCmp); int m = 0; for(int i = 0; i
1 && dcmp(Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2])) <= 0) m--; ch[m++] = p[i]; } int k = m; for(int i = n-2; i >= 0; i--) { ///去掉等号就共线了,不过,都要注意重点问题哦 while(m > k && dcmp(Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2])) <= 0) m--; ch[m++] = p[i]; } if(n > 1) m--; return m; } double Dis(Point A, Point B) { return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y)); } int main() { int m; cin>>n; /**输入数组*/ for(int i = 0; i < n; i++) { int a,b; cin>>a>>b; p[i] = Point(a,b); } int len=ConvexHull(); //...再操作 }
相关练习链接:
hdu4946(Andrew算法) : http://blog.youkuaiyun.com/u014576894/article/details/38703517
hdu1392( Andrew 算法 ):
http://blog.youkuaiyun.com/u014576894/article/details/38959023
poj11
13 (Graham_scan算法):http://blog.youkuaiyun.com/u014576894/article/details/38867259