凸包 模板

我的凸包,第一个自己写的凸包,花了两天时间终于把这个算法完全搞明白了,其中有点小纠结的就是我自己写程序是忘记了把最终结果四舍五入,一直不知道问题出在什么地方;

其实这个算法不难理解,就是其中的那个左旋还是右旋的判断一直感觉不好实现,感觉不好证明。给个大牛的链接吧:http://www.cnblogs.com/devymex/archive/2010/08/09/1795392.html 

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
struct ss{
 double x,y;
}po[1003];
ss p11;
double dis(ss p1,ss p2) //计算两点之间的距离
{
 return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}

double judge(ss p1,ss p2,ss p3)//判断极角的大小
{
 return (p1.x-p2.x)*(p3.y-p2.y)-(p3.x-p2.x)*(p1.y-p2.y);
}
int cmp(ss p1,ss p2)//排序函数
{
 if(judge(p1,p11,p2)>0)return 1;
 else if(judge(p1,p11,p2)==0.0&&dis(p1,p11)<dis(p2,p11))
  return 1;
 else return 0;
}
int Graham(int n)  //算法核心
{
 int m=2,t;
    for (t=3;t<=n;t++)
    {
  while (judge(po[t],po[m],po[m-1])<0.001)
  {
   if(m==2)
   {
    po[m]=po[t];
    t++;
   }
   else m--;
  }
  po[++m]=po[t];
    }
 return m;
}
int main()
{
 int i,n,c,j;
 double sum;
 while (cin>>n>>c)
 {
  p11.x=p11.y=1000000;  //p11用于找基准点
  for (i=1;i<=n;i++)
  {
   cin>>po[i].x>>po[i].y;
            if(po[i].y<p11.y)
   { j=i; p11=po[i];}
   else if(po[i].y==p11.y&&po[i].x<p11.x)
   {j=i;p11=po[i];}
  }
     ss w;
  w=po[1];
  po[1]=p11;
  po[j]=w;
  sort(po+2,po+1+n,cmp);
  int len=Graham(n);
  sum=0.0;
  for (i=1;i<len;i++)
  {
   sum+=dis(po[i],po[i+1]);
  }
  sum+=dis(po[i],po[1]);
  sum+=(2*3.1415926*c);
  int m=int(sum+0.5);
  cout<<m<<endl;
 }
 return 0;
}

 网上的代码: 

#include <iostream>
#include <string>
#include <cmath>
#include <algorithm>
using namespace std;

const double eps = 1e-8;
struct point
{
	double x,y;
}po[1003];


double cross(point& p1,point& p2,point& p3)//判断夹角的大小
{
	return (p1.x-p2.x)*(p3.y-p2.y)-(p1.y-p2.y)*(p3.x-p2.x);
}


bool cmp(point a,point b) //找基点
{
	if(a.y==b.y)
		return a.x<b.x;
	else return a.y<b.y;	
}

point p11;

double dis(point& p1,point& p2) //计算两点之间的距离
{
	return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}


bool cmpPolor(point& p1,point& p2)//极角排序用atan2从第三象限-pi转一圈到第四象限pi
{
	double t=cross(p1,p11,p2);
	if(t==0)
		return dis(p1,p11)<=dis(p2,p11);
	else if(t>0)
		return 1;
	else return 0;
}


int graham(int n)
{
	sort(po+1,po+n+1,cmp);
	p11=po[1];
	po[0]=po[n];//这个是起到哨兵作用
	
	sort(po+2,po+n+1,cmpPolor);//对剩下的点进行极角排序
	
	int m=2;
	int t;
	for(t=3;t<=n;t++)//首先前三个元素入栈
	{
		while(cross(po[t],po[m],po[m-1])<=eps)//如果两者是右旋关系,那么把当前的m点出栈,把i点入站
		{
		if(m == 2)//如果当前栈中只有两个元素,那么把当前i值给po【2】
			{
				swap(po[m],po[t]);
				t++;
			}
			else 
			m--;
		}
		m++;
		swap(po[m],po[t]);
	}
	return m;
}

int main()
{
	int n,c,i;
	while(scanf("%d%d",&n,&c)!=EOF)
	{
		for(i=1;i<=n;i++)
		{
			scanf("%lf%lf",&po[i].x,&po[i].y);
		}
		int len = graham(n);
		
		double t=0;
		for(i=1;i<len;i++)
		{
			t+=dis(po[i],po[i+1]);	
		}
		t+=dis(po[1],po[len]);
		printf("%.0lf\n",3.1415926535897*2.0*c+t);
	}
	return 0;
}

 

posted @ 2011-11-08 21:13  我们一直在努力  阅读(173)  评论(0编辑  收藏  举报