bzoj1069: [SCOI2007]最大土地面积 凸包+旋转卡壳求最大四边形面积
在某块平面土地上有N个点,你可以选择其中的任意四个点,将这片土地围起来,当然,你希望这四个点围成的多边形面积最大。
题解:先求出凸包,O(n)枚举旋转卡壳,O(n)枚举另一个点,求最大四边形面积
/************************************************************** Problem: 1069 User: walfy Language: C++ Result: Accepted Time:892 ms Memory:1360 kb ****************************************************************/ //#pragma comment(linker, "/stack:200000000") //#pragma GCC optimize("Ofast,no-stack-protector") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") //#pragma GCC optimize("unroll-loops") #include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pi acos(-1.0) #define ll long long #define vi vector<int> #define mod 10007 #define C 0.5772156649 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define pil pair<int,ll> #define pli pair<ll,int> #define pii pair<int,int> #define cd complex<double> #define ull unsigned long long #define base 1000000000000000000 #define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double eps=1e-6; const int N=2000+10,maxn=5000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f; struct point{ ll x,y; }; point p[N],s[N]; int top,n; ll dir(point p1,point p2,point p3) { return (p3.x-p2.x)*(p2.y-p1.y)-(p3.y-p2.y)*(p2.x-p1.x); } ll dis(point a,point b) { return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y); } ll area(point p1,point p2,point p3) { return fabs(dir(p1,p2,p3)); } bool cmp(point a,point b) { ll te=dir(p[0],a,b); if(te<0)return 1; if(te==0&&dis(p[0],a)<dis(p[0],b))return 1; return 0; } void graham() { int pos,minx,miny; minx=miny=inf; for(int i=0;i<n;i++) { if(p[i].x<minx||(p[i].x==minx&&p[i].y<miny)) { minx=p[i].x; miny=p[i].y; pos=i; } } swap(p[0],p[pos]); sort(p+1,p+n,cmp); p[n]=p[0]; s[0]=p[0],s[1]=p[1],s[2]=p[2]; top=2; for(int i=3;i<=n;i++) { while(dir(s[top-1],s[top],p[i])>=0&&top>=2)top--; s[++top]=p[i]; } ll ans=0; for(int i=0;i<top;i++) { int j,a1=(i+1)%top,a2=(i+3)%top; for(j=(i+2)%top;j!=i;j=(j+1)%top) { while(a1!=j&&area(s[(a1+1)%top],s[i],s[j])>=area(s[a1],s[i],s[j]))a1=(a1+1)%top; while(a2!=i&&area(s[(a2+1)%top],s[i],s[j])>=area(s[a2],s[i],s[j]))a2=(a2+1)%top; ans=max(ans,area(s[a1],s[i],s[j])+area(s[a2],s[i],s[j])); } } printf("%.3f\n",1.0*ans/2); } int main() { scanf("%d",&n); for(int i=0;i<n;i++) scanf("%lld%lld",&p[i].x,&p[i].y); graham(); return 0; } /******************** ********************/