夫約翰想要建造一個圍欄用來圍住他的奶牛,可是他資金匱乏。他建造的圍欄必須包括他的奶牛喜歡吃草的所有地點。對于給出的這些地點的坐標,計算最短的能夠圍住這些點的圍欄的長度。
輸入
輸入數據的第一行包括一個整數 N。N(0 <= N <= 10,000)表示農夫約翰想要圍住的放牧點的數目。接下來 N 行,每行由兩個實數組成,Xi 和 Yi,對應平面上的放牧點坐標(-1,000,000 <= Xi,Yi <= 1,000,000)。數字用小數表示。
輸出
輸出必須包括一個實數,表示必須的圍欄的長度。答案保留兩位小數。
樣例輸入
4
4 8
4 12
5 9.3
7 8
樣例輸出
12.00
不說了
凸包模板題
維護了凸包后計算相鄰兩個點之間的距離
#include<bits/stdc++.h>
using namespace std;
#define eps 1e-5
inline int read(){char ch=getchar();int res=0;while(!isdigit(ch)) ch=getchar();while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar();return res;
}
int n,m;
struct point{double x,y;point(){}point (int a,int b):x(a),y(b){};friend inline point operator -(const point &a,const point &b){return point(a.x-b.x,a.y-b.y);}friend inline double operator *(const point &a,const point &b){return (a.x*b.y-a.y*b.x);}inline double calc()const{return x*x+y*y;}
}p[10005],q[10005];
inline bool comp(const point &a,const point &b){double det=(a-p[1])*(b-p[1]);if(fabs(det)>=eps) return det>0;return a.calc()<b.calc();
}
inline double coun(point a,point b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
inline void graham(){int date=1;for(int i=2;i<=n;i++){if(p[i].x<p[date].x||(p[i].x==p[date].x&&p[i].y<p[date].y))date=i;}if(date!=1) swap(p[date],p[1]);sort(p+2,p+1+n,comp);q[++m]=p[1];for(int i=2;i<=n;i++){while(m>=3&&((q[m]-q[m-1])*(p[i]-q[m-1])<=eps))m--;q[++m]=p[i];}q[m+1]=p[1];
}
inline double cal(){double ans=0;for(int i=1;i<=m;i++){ans+=coun(q[i+1],q[i]);}return ans;
}
int main(){n=read();for(int i=1;i<=n;i++){cin>>p[i].x>>p[i].y;}graham();double s=cal();printf("%.2lf\n",s);
}