研究一下,学习了个Graham-Scan求凸包的方法,主要用了排序,栈,还有叉积。下面是求周长和面积的模板。
#include <cstdio>
#include <cmath>
#include <algorithm>
#define FOR(i,x,y) for(int i=x;i<=y;++i)
using namespace std;
const double eps=1e-10;
int n,top,location;
double len,area,temp,px,py;
struct k
{
double x,y;
}result[110],tree[110];// 模拟堆栈S,保存凸包上的点
double dis(k p1,k p2)
{
return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
double mul(k p1,k p2,k p3) // 叉积
{
return ((p2.x-p1.x)*(p3.y-p1.y)-(p2.y-p1.y)*(p3.x-p1.x));
}
bool cmp(k a,k b)
{
double m;
m=mul(tree[0],a,b);
if(m<0) return 0;
else if(m==0&&(dis(tree[0],a)<dis(tree[0],b))) return 0;
return 1;
}
void Tubao()
{
top=2;
FOR(i,0,2)
{
result[i].x=tree[i].x;
result[i].y=tree[i].y;
}
FOR(i,3,n)
{
while(mul(result[top-1],result[top],tree[i])<=0&&top>2) --top;//出栈
result[top+1].x=tree[i].x;
result[top+1].y=tree[i].y;
++top;
}
}
int main ()
{
while(scanf("%d",&n)!=EOF&&n)
{
py=0x3f3f3f; len=0.0; area=0.0;
FOR(i,0,n-1) scanf("%lf%lf",&tree[i].x,&tree[i].y);
if(n==1)
{
printf("0.00\n");
continue;
}
else if(n==2)
{
printf("%.2f\n",dis(tree[0],tree[1]));
continue;
}
FOR(i,0,n-1)//找出y最小的点
{
if(tree[i].y<py)
{
px=tree[i].x;
py=tree[i].y;
location=i;
}
else if(tree[i].y-py<eps&&tree[i].x<px)
{
px=tree[i].x;
py=tree[i].y;
location=i;
}
}
temp=tree[0].x;//把y最小的移到tree[0]
tree[0].x=tree[location].x;
tree[location].x=temp;
temp=tree[0].y;
tree[0].y=tree[location].y;
tree[location].y=temp;
sort(tree+1,tree+n,cmp);
tree[n].x=tree[0].x;
tree[n].y=tree[0].y;
Tubao();
FOR(i,0,top-1) len+=dis(result[i],result[i+1]);
FOR(i,0,top-1) area+=mul(result[0],result[i],result[i+1]);
area=fabs(area)/2;
printf("%.2f\n%.2f",len,area);
}
return 0 ;
}
浙公网安备 33010602011771号