凸包 模板
我的凸包,第一个自己写的凸包,花了两天时间终于把这个算法完全搞明白了,其中有点小纠结的就是我自己写程序是忘记了把最终结果四舍五入,一直不知道问题出在什么地方;
其实这个算法不难理解,就是其中的那个左旋还是右旋的判断一直感觉不好实现,感觉不好证明。给个大牛的链接吧: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; }