洛谷 P2742 [USACO5.1]圈奶牛Fencing the Cows || 凸包模板

整篇都是仅做记录...

蓝书上的板子。水平序,单调栈。先求下凸包,再求上凸包。叉积的作用是判定向量的位置关系。

48行的作用是在求上凸包的时候不至于去删下凸包中的点。上凸包中第一个点被认为是t1。

另:如果不希望在凸包边上有输入点(指多点共线且在凸包上时都当做在凸包上的,而不是像这个一样仅保留第一个和最后一个),将>=改成>

另:蓝书上原文是把叉积的两个参数互换,然后<=0。实际没有区别。

另:如果需要去掉得到凸包的最后多余一个点(与第一个是一样的),那么要加一句:

if(n>1)    m--;

另:蓝书上那张图(示意)

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cmath>
 4 using namespace std;
 5 const double eps=1e-7;
 6 struct Point
 7 {
 8     double x,y;
 9     Point(double x1=0,double y1=0):x(x1),y(y1){}
10     friend bool operator<(const Point& a,const Point& b)
11     {
12         return a.x<b.x||(a.x==b.x&&a.y<b.y);
13     }
14 }p[10100],ans[10100];
15 int top;
16 double anss;
17 int dcmp(double a)
18 {
19     if(fabs(a)<eps)    return 0;
20     return a>0?a:-a;
21 }
22 double cross(const Point& a,const Point& b)
23 {
24     return a.x*b.y-b.x*a.y;
25 }
26 Point operator-(const Point& a,const Point& b)
27 {
28     return Point(a.x-b.x,a.y-b.y);
29 }
30 double len(const Point& x)
31 {
32     return sqrt(x.x*x.x+x.y*x.y);
33 }
34 int n;
35 int main()
36 {
37     int i;
38     scanf("%d",&n);
39     for(i=1;i<=n;i++)
40         scanf("%lf%lf",&p[i].x,&p[i].y);
41     sort(p+1,p+n+1);
42     for(i=1;i<=n;i++)
43     {
44         //while(top>1&&cross(p[i]-ans[top-2],ans[top-1]-ans[top-2])>0)    --top;
45         while(top>1&&cross(p[i]-ans[top-2],ans[top-1]-ans[top-2])>=0)    --top;
46         ans[top++]=p[i];
47     }
48     int t1=top;
49     for(i=n-1;i>=1;i--)
50     {
51         while(top>t1&&cross(p[i]-ans[top-2],ans[top-1]-ans[top-2])>=0)    --top;
52         ans[top++]=p[i];
53     }
54     for(i=1;i<top;i++)
55         anss+=len(ans[i]-ans[i-1]);
56     printf("%.2lf",anss);
57     return 0;
58 }
posted @ 2017-11-07 22:10  hehe_54321  阅读(269)  评论(0编辑  收藏  举报
AmazingCounters.com