凸包入门

xiaoxiao2021-02-28  59

什么是凸包?

假设平面上有p0~p12共13个点,过某些点作一个多边形,使这个多边形能把所有点都“包”起来。当这个多边形是凸多边形的时候,我们就叫它“凸包”。如下图: 

然后,什么是凸包问题?  我们把这些点放在二维坐标系里面,那么每个点都能用 (x,y) 来表示。  现给出点的数目13,和各个点的坐标。求构成凸包的点?

自己才刚刚接触到这个数学问题。通过几个入门的简单的题,基本上已经有了简单的了解。所以自己先写点东西。为了自己以后

可以好好的复习。

其实凸包就是凸多边形问题。

大佬的博客:凸包五解

                    点击打开链接

   1 凸包问题要求什么?

一般的话来说,入门就是要你找出这个凸多边型,求凸多边的型的面积,周长。其实写到这就可以思考一下,如何求多边。只要

把多边形求出来,那么相对来说就是可以找到周长,面积了。

  2: 如何求? 其实大佬的博客中,将这个思想已经完全的讲解出来了。

(1)点的输入

(2)找出很明显的凸包上点的,作为一个开头。

(3)极角排序。

int dis(node c1,node c2) {     return (c1.x-c2.x)*(c1.x-c2.x)+(c1.y-c2.y)*(c1.y-c2.y); } double mutil(node c0,node c1,node c2) {     return (c1.x-c0.x)*(c2.y-c0.y)-(c2.x-c0.x)*(c1.y-c0.y); } int cmp(node c1,node c2) {     int x=mutil(c1,c2,a[0]);     if(x>0||(x==0&&dis(c1,a[0])<dis(c2,a[0])))         return 1;     else         return 0; }

(4)开始扫描,利用叉乘来判断是不是凸包上的点,将凸包上的点收入到栈堆中(数组也可以)

void Graham() {     tot=2;     p[0]=a[0],p[1]=a[1];     for(int i=2; i<n; i++)     {         while(tot>1&&mutil(p[tot-1],p[tot-2],a[i])>=0)             tot--;         p[tot++]=a[i];     } }

俩个简单的题

 NYOJ-78 圈水池 入门凸包输出点

int n,tot; struct node {     int x,y; } a[10005],p[10005]; int dis(node c1,node c2) {     return (c1.x-c2.x)*(c1.x-c2.x)+(c1.y-c2.y)*(c1.y-c2.y); } double mutil(node c0,node c1,node c2) {     return (c1.x-c0.x)*(c2.y-c0.y)-(c2.x-c0.x)*(c1.y-c0.y); } int cmp(node c1,node c2) {     int x=mutil(c1,c2,a[0]);     if(x>0||(x==0&&dis(c1,a[0])<dis(c2,a[0])))         return 1;     else         return 0; } int cmp1(node a,node b) {     if(a.x==b.x)         return a.y<b.y;     else         return a.x<b.x; } void Graham() {     tot=2;     p[0]=a[0],p[1]=a[1];     for(int i=2; i<n; i++)     {         while(tot>1&&mutil(p[tot-1],p[tot-2],a[i])>=0)             tot--;         p[tot++]=a[i];     }     sort(p,p+tot,cmp1);     for(int i=0;i<tot;i++)         printf("%d %d\n",p[i].x,p[i].y); } int main() {     int T;     scanf("%d",&T);     while(T--)     {         scanf("%d",&n);         for(int i=0; i<n; i++)         {             scanf("%d%d",&a[i].x,&a[i].y);         }         int k=0;         for(int i=0; i<n; i++)         {             if(a[i].y<a[k].y||(a[i].y==a[k].y&&a[i].x<a[k].x))                 k=i;         }         swap(a[0],a[k]);         sort(a+1,a+n,cmp); //        for(int i=0; i<n; i++) //        { //            printf("******%d %d\n",a[i].x,a[i].y); //        }         Graham();     } }

 POJ-3348 Cows 入门求面积

 void Graham()     {         tot=2;         p[0]=a[0],p[1]=a[1];         for(int i=2; i<n; i++)         {             while(tot>1&&mutil(p[tot-1],p[tot-2],a[i])>=0)                 tot--;             p[tot++]=a[i];         }         int sum=0;         for(int i=2; i<tot; i++)         {             int l=(int)mutil(p[0],p[i-1],p[i]);                   //在求面积的时候就可以直接用向量来求。即平行四边的面积             就等于两条边的乘积除以2;             sum+=abs(l)/2;         }         printf("%d",sum/50);     }

转载请注明原文地址: https://www.6miu.com/read-69957.html

最新回复(0)