题目描述
农夫约翰想要建造一个围栏用来围住他的奶牛,可是他资金匮乏。他建造的围栏必须包括他的奶牛喜欢吃草的所有地点。对于给出的这些地点的坐标,计算最短的能够围住这些点的围栏的长度。
输入输出格式
输入格式:
输入数据的第一行包括一个整数 N。N(0 <= N <= 10,000)表示农夫约翰想要围住的放牧点的数目。接下来 N 行,每行由两个实数组成,Xi 和 Yi,对应平面上的放牧点坐标(-1,000,000 <= Xi,Yi <= 1,000,000)。数字用小数表示。
输出格式:
输出必须包括一个实数,表示必须的围栏的长度。答案保留两位小数。
输入输出样例
说明
题目翻译来自NOCOW。
USACO Training Section 5.1
凸包模板题
坑点,一定要注意int 和double,debug一个晚上+早读
NOF:一定要注意细节
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #define PI 3.1415926535 7 #define DB double 8 #define eps 1e-8 9 using namespace std; 10 const int N=12000; 11 int T,n,L; 12 struct node{ 13 DB x,y; 14 }d[N],s[N]; 15 bool cmp1(node a,node b) 16 { 17 if(a.y!=b.y) return a.y<b.y; 18 else return a.x<b.x; 19 } 20 DB Cross(node a1,node a2,node b1,node b2) 21 { 22 return (a2.x-a1.x)*(b2.y-b1.y)-(b2.x-b1.x)*(a2.y-a1.y); 23 } 24 DB dis(node a,node b) 25 { 26 return sqrt((a.x-b.x)*(a.x-b.x)*1.0+(a.y-b.y)*(a.y-b.y)); 27 } 28 bool cmp2(node a,node b) 29 { 30 DB m=Cross(d[1],a,d[1],b); 31 if(m>0) return 1; 32 else if(m==0) return dis(d[0],a)<dis(d[0],b); 33 return 0; 34 } 35 int top; 36 DB ans; 37 int main() 38 { 39 freopen("fc.in","r",stdin); 40 freopen("fc.out","w",stdout); 41 scanf("%d",&n); 42 for(int i=1;i<=n;++i)scanf("%lf%lf",&d[i].x,&d[i].y); 43 sort(d+1,d+n+1,cmp1); 44 s[++top]=d[1]; 45 sort(d+2,d+n+1,cmp2); 46 s[++top]=d[2]; 47 for(int i=3;i<=n;++i) 48 { 49 while(top>=2 && Cross(s[top-1],s[top],s[top],d[i])<=0) top--; 50 s[++top]=d[i]; 51 } 52 for(int i=1;i<top;++i)ans+=dis(s[i],s[i+1]); 53 ans+=dis(s[1],s[top]); 54 printf("%.2lf\n",ans); 55 return 0; 56 }
君子之心事,天青日白,不可使人不知;君子之才华,玉韫珠藏,不可使人易知