bzoj 1069: [SCOI2007]最大土地面积

求出凸包,枚举一下对角线,然后就可以用神奇的旋转卡壳了(其实感觉旋转卡壳就是用凸包的性质给暴力加了一点小优化)

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cmath>
 4 using namespace std;
 5 int n,top;
 6 double ans;
 7 struct point{double x,y;}p[2005],s[2005];
 8 double dis(point a, point b)
 9 {
10     return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y); 
11 }
12 point operator - (point a, point b)
13 {
14     point t; t.x=a.x-b.x; t.y=a.y-b.y; return t;
15 }
16 double operator * (point a, point b)
17 {
18     return a.x*b.y-a.y*b.x;
19 }
20 bool operator < (point a, point b)
21 {
22     if ((a-p[1])*(b-p[1])==0) return dis(a,p[1])<dis(b,p[1]);
23     return (a-p[1])*(b-p[1])>0;
24 }
25 void Graham()
26 {
27     int k=1; 
28     for (int i=2; i<=n; i++) 
29         if (p[k].y>p[i].y || (p[k].y==p[i].y && p[k].x>p[i].x)) k=i;
30     swap(p[1],p[k]); sort(p+2,p+n+1);
31     s[++top]=p[1]; s[++top]=p[2];
32     for (int i=3; i<=n; i++)
33     {
34         while (top>1 && (s[top]-p[i])*(s[top-1]-p[i])>=0) top--;
35         s[++top]=p[i];
36     }
37 }
38 void RC()
39 {
40     s[top+1]=p[1];
41     int a,b;
42     for (int x=1; x<=top; x++)
43     {
44         a=x%top+1; b=(x+2)%top+1;
45         for (int y=x+2; y<=top; y++)
46         {
47             while (a%top+1!=y && (s[y]-s[x])*(s[a+1]-s[x])<(s[y]-s[x])*(s[a]-s[x])) a=a%top+1;
48             while (b%top+1!=x && (s[b+1]-s[x])*(s[y]-s[x])<(s[b]-s[x])*(s[y]-s[x])) b=b%top+1;
49             ans=max(ans,-((s[y]-s[x])*(s[a]-s[x])+(s[b]-s[x])*(s[y]-s[x])));
50         }
51     }
52 }
53 int main()
54 {
55     scanf("%d",&n);
56     for (int i=1; i<=n; i++) scanf("%lf%lf",&p[i].x,&p[i].y);
57     Graham(); RC();
58     printf("%.3lf",ans/2);
59     return 0;
60 }

 

posted @ 2017-03-02 07:14  ws_ccd  阅读(201)  评论(0编辑  收藏  举报