bzoj1069 [SCOI2007]最大土地面积 旋转卡壳

1069: [SCOI2007]最大土地面积

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 3767  Solved: 1501
[Submit][Status][Discuss]

Description

  在某块平面土地上有N个点,你可以选择其中的任意四个点,将这片土地围起来,当然,你希望这四个点围成
的多边形面积最大。

Input

  第1行一个正整数N,接下来N行,每行2个数x,y,表示该点的横坐标和纵坐标。

Output

  最大的多边形面积,答案精确到小数点后3位。

Sample Input

5
0 0
1 0
1 1
0 1
0.5 0.5

Sample Output

1.000

HINT

数据范围 n<=2000, |x|,|y|<=100000

 先求凸包,然后n^2枚举对角线,用旋转卡壳去找位于对角线两侧且到对角线距离最大的两点构成2个三角形,2个三角形面积和就是四边形面积

 1 #include<bits/stdc++.h>
 2 #define N 2010
 3 using namespace std;
 4 int n,tp;
 5 struct P{
 6     double x,y;
 7     bool operator < (const P &b)const{
 8         return x==b.x?y<b.y:x<b.x;
 9     }
10     P operator - (const P &b)const{
11         return (P){x-b.x,y-b.y};
12     }
13 }a[N],s[N];
14 double crs(P a,P b){return a.x*b.y-a.y*b.x;}
15 void getbag(){
16     sort(a+1,a+1+n);
17     for(int i=1;i<=n;i++){
18         while(tp>1&&crs(a[i]-s[tp-1],s[tp]-s[tp-1])>=0)--tp;
19         s[++tp]=a[i];
20     }
21     int now=tp;
22     for(int i=n-1;i>=1;i--){
23         while(tp>now&&crs(a[i]-s[tp-1],s[tp]-s[tp-1])>=0)--tp;
24         s[++tp]=a[i];
25     }
26     if(n>1)--tp;
27 }
28 
29 void getans(){
30     double ans=0;s[tp+1]=s[1];
31     for(int i=1;i<=tp-2;i++){
32         int a=i+1,b=(i+2)%tp+1;
33         for(int j=i+2;j<=tp;j++){
34             while(a%tp+1!=j&&crs(s[a]-s[i],s[j]-s[i])<crs(s[a+1]-s[i],s[j]-s[i]))a=a%tp+1;
35             while(b%tp+1!=i&&crs(s[j]-s[i],s[b]-s[i])<crs(s[j]-s[i],s[b+1]-s[i]))b=b%tp+1;
36             ans=max(ans,(crs(s[a]-s[i],s[j]-s[i])+crs(s[j]-s[i],s[b]-s[i]))/2);
37         }
38     }
39     printf("%.3lf
",ans);
40 }
41 
42 int main(){
43     scanf("%d",&n);
44     for(int i=1;i<=n;i++)
45     scanf("%lf%lf",&a[i].x,&a[i].y);
46     getbag();getans();
47     return 0;
48 }
原文地址:https://www.cnblogs.com/wsy01/p/8193910.html