凸包问题

凸包问题 —— 两种算法

第一种算法: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(); //...再操作 } 
            
           
         
        
        
       
       
      
      
     
     

相关练习链接:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值