bzoj 1670 [Usaco2006 Oct]Building the Moat护城河的挖掘

Time Limit: 3 Sec  Memory Limit: 64 MB
Submit: 347  Solved: 255
[Submit][Status][Discuss]

Description

为了防止口渴的食蚁兽进入他的农场,Farmer John决定在他的农场周围挖一条护城河。农场里一共有N(8<=N<=5,000)股泉水,并且,护城河总是笔直地连接在河道上的相邻的两股泉水。护城河必须能保护所有的泉水,也就是说,能包围所有的泉水。泉水一定在护城河的内部,或者恰好在河道上。当然,护城河构成一个封闭的环。 挖护城河是一项昂贵的工程,于是,节约的FJ希望护城河的总长度尽量小。请你写个程序计算一下,在满足需求的条件下,护城河的总长最小是多少。 所有泉水的坐标都在范围为(1..10,000,000,1..10,000,000)的整点上,一股泉水对应着一个唯一确定的坐标。并且,任意三股泉水都不在一条直线上。 以下是一幅包含20股泉水的地图,泉水用"*"表示


图中的直线,为护城河的最优挖掘方案,即能围住所有泉水的最短路线。 路线从左上角起,经过泉水的坐标依次是:(18,0),(6,-6),(0,-5),(-3,-3),(-17,0),(-7,7),(0,4),(3,3)。绕行一周的路径总长为70.8700576850888(...)。答案只需要保留两位小数,于是输出是70.87。

 

Input

* 第1行: 一个整数,N * 第2..N+1行: 每行包含2个用空格隔开的整数,x[i]和y[i],即第i股泉水的位 置坐标

Output

* 第1行: 输出一个数字,表示满足条件的护城河的最短长度。保留两位小数

Sample Input

20
2 10
3 7
22 15
12 11
20 3
28 9
1 12
9 3
14 14
25 6
8 1
25 1
28 4
24 12
4 15
13 5
26 5
21 11
24 4
1 8

Sample Output

70.87
题解:
  一道裸的求凸包周长。讲解:Graham's Scan法求解凸包问题
  旋转卡壳,有待学习。
 1 #include<cstring>
 2 #include<cmath>
 3 #include<iostream>
 4 #include<cstdio>
 5 #include<algorithm>
 6 
 7 #define N 5007
 8 #define ll long long
 9 using namespace std;
10 inline int read()
11 {
12     int x=0,f=1;char ch=getchar();
13     while(ch>'9'||ch<'0'){if (ch=='-') f=-1;ch=getchar();}
14     while(ch<='9'&&ch>='0')
15     {
16         x=(x<<3)+(x<<1)+ch-'0';
17         ch=getchar();
18     }
19     return x*f;
20 }
21 
22 int n,top;
23 struct Node
24 {
25     int x,y;
26 }a[N],b[N];
27 double ans=0;
28 
29 inline ll sqr(ll x){return x*x;}
30 inline Node operator-(Node x,Node y){return (Node){x.x-y.x,x.y-y.y};}
31 inline ll operator*(Node x,Node y){return x.x*y.y-x.y*y.x;}
32 inline ll dis(Node x,Node y)
33 {
34     return sqr(x.x-y.x)+sqr(x.y-y.y);
35 }
36 bool cmp(Node x,Node y)
37 {
38     ll t=(x-a[1])*(y-a[1]);
39     if (t==0) return dis(a[1],x)<dis(a[1],y);
40     return t>0;
41 }
42 void graham()
43 {
44     int t=1;
45     for (int i=2;i<=n;i++)
46         if (a[i].y<a[t].y||(a[i].y==a[t].y&&a[i].x<a[t].x)) t=i;//平面直角坐标系里最左下那个点。
47     swap(a[1],a[t]);
48     sort(a+2,a+n+1,cmp);     
49     b[++top]=a[1],b[++top]=a[2];
50     for (int i=3;i<=n;i++)
51     {
52         while((b[top]-b[top-1])*(a[i]-b[top-1])<=0) top--;
53         b[++top]=a[i];
54     }
55     b[top+1]=a[1];
56     for (int i=1;i<=top;i++)
57         ans+=sqrt(dis(b[i],b[i+1]));
58 }
59 int main()
60 {
61     n=read();
62     for (int i=1;i<=n;a[i].x=read(),a[i].y=read(),i++);
63     graham();
64     printf("%.2lf\n",ans);
65 }

 

 
posted @ 2017-12-08 15:22  Kaiser-  阅读(152)  评论(0编辑  收藏  举报