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;
}
/********************
 
********************/
View Code

 

posted @ 2018-05-22 20:41  walfy  阅读(500)  评论(0编辑  收藏  举报