bzoj 1069 最大土地面积
题目大意:
一些点,选四个点使这围成的四边形面积最大
思路:
首先可以知道这些点一定在凸包上,然后graham求一下凸包
然后我们可以枚举对角线在两边找最远的点
然而这样复杂度爆了
所以我们可以利用旋转卡壳的思想
枚举对角线的时候确定一个点,然后旋转另一个点,如果确定了另外两个点,则另外两个点也一起转
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<cstdlib>
5 #include<set>
6 #include<vector>
7 #include<cmath>
8 #include<algorithm>
9 #define inf 2147483611
10 #define ll long long
11 using namespace std;
12 inline int read()
13 {
14 int x=0,f=1;char ch=getchar();
15 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
16 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
17 return x*f;
18 }
19 int n,top;
20 struct node
21 {
22 double x,y;
23 node operator - (const node &a) const
24 {
25 return (node) {x-a.x,y-a.y};
26 }
27 double operator * (const node &a) const
28 {
29 return x*a.y-y*a.x;
30 }
31 }pt[2005],st[2005];
32 double dis(node a,node b) {return hypot(fabs(a.x-b.x),fabs(a.y-b.y));}
33 bool cmp(node a,node b)
34 {
35 double t=(a-pt[1])*(b-pt[1]);
36 if(t==0)return dis(a,pt[1])<dis(b,pt[1]);
37 return t<0;
38 }
39 void G()
40 {
41 int k=1;
42 for(int i=2;i<=n;i++)
43 if(pt[k].y>pt[i].y||(pt[k].y==pt[i].y&&pt[k].x>pt[i].x)) k=i;
44 swap(pt[1],pt[k]);
45 sort(pt+2,pt+n+1,cmp);
46 st[++top]=pt[1];st[++top]=pt[2];
47 for(int i=3;i<=n;i++)
48 {
49 while(top>1&&(pt[i]-st[top-1])*(st[top]-st[top-1])<=0) top--;
50 st[++top]=pt[i];
51 }
52 }
53 int main()
54 {
55 n=read();
56 for(int i=1;i<=n;i++) scanf("%lf%lf",&pt[i].x,&pt[i].y);
57 G();
58 st[top+1]=pt[1];
59 double ans=0;
60 int l,r;
61 for(int i=1;i<=top;i++)
62 {
63 l=i%top+1;r=(i+2)%top+1;
64 for(int j=i+2;j<=top;j++)
65 {
66 while(l%top+1!=j&&(st[j]-st[i])*(st[l+1]-st[i])>(st[j]-st[i])*(st[l]-st[i])) l=l%top+1;
67 while(r%top+1!=i&&(st[r+1]-st[i])*(st[j]-st[i])>(st[r]-st[i])*(st[j]-st[i])) r=r%top+1;
68 ans=max((st[j]-st[i])*(st[l]-st[i])+(st[r]-st[i])*(st[j]-st[i]),ans);
69 }
70 }
71 printf("%.3lf",ans/2.0);
72 return 0;
73 }
74