1. 程式人生 > >bzoj1069 [SCOI2007]最大土地面積 旋轉卡殼

bzoj1069 [SCOI2007]最大土地面積 旋轉卡殼

clas double 就是 旋轉 status operator 多邊形 i++ 其中

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\n",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 }

bzoj1069 [SCOI2007]最大土地面積 旋轉卡殼