求凸包的周長(計算幾何模板)
阿新 • • 發佈:2019-02-20
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int N = 110;
const double eps = 1e-8;
const double PI = 3.1415926535898;
struct point
{
double x,y;
}s[N],t[N];
bool isZero(double x)
{
return (x>0?x:-x)<eps;
}
double dis(point a,point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
//叉積
double crossProd(point a,point b,point c)
{
return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}
//以最左下的點為基準點,其他各點(逆時針方向)以極角從小到大的排序規則
int cmp(const void * a,const void * b)
{
point *c = (point *)a;
point *d = (point *)b;
double k = crossProd(t[0],*c,*d);
if(k<eps||(isZero(k) && (dis(t[0],*c)>dis(t[0],*d))))
return 1;
return -1;
}
double Graham(int n) {
double x = t[0].x;
double y = t[0].y;
int k = 0;
for (int i=1; i<n; ++i)
{//找到最左下的一個點
if (t[i].x<x || (t[i].x==x && t[i].y<y)) {
x = t[i].x;
y = t[i].y;
k = i;
}
}
//交換,將最左的點移至陣列首位
point tmp = t[k];
t[k] = t[0];
t[0] = tmp;
qsort(t+1, n-1, sizeof(point), cmp);
// sort(t+1,n-1,cmp);
t[n] = t[0];
s[0] = t[0];
s[1] = t[1];
s[2] = t[2];
int top = 2;
for (int i=3; i<=n; ++i)
{//加入一個點後,向右偏拐或共線,則上一個點不在凸包內,則--top,該過程直到不向右偏拐或沒有三點共線的點
while (crossProd(s[top-1], s[top], t[i])<=eps && top>=2) --top;
s[++top] = t[i];//在當前情況下符合凸包的點,入棧
}
double len = 0;
for (int i=0; i<top; ++i) len += dis(s[i], s[i+1]);
return len;
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int n;
double r;
scanf("%d%lf",&n,&r);
for(int i=0;i<n;i++)
{
scanf("%lf%lf",&t[i].x,&t[i].y);
}
if(n==1)
{
printf("%.2lf\n",2*PI*r);
}
else if(n==2)
{
printf("%.2lf\n",2*(PI*r+dis(t[0],t[1])));
}
else
{
printf("%.2lf\n",Graham(n)+2*PI*r);
}
return 0;
}