bzoj 1069

最开始想到的是枚举3个点,另一个点用卡壳的思想,但实际上可以只枚举两个点(对角线上的两个点),其余两个点用卡壳。

/**************************************************************
    Problem: 1069
    User: idy002
    Language: C++
    Result: Accepted
    Time:232 ms
    Memory:880 kb
****************************************************************/

#include <cstdio>
#include <cmath>
#include <algorithm>
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define eps 1e-10
#define N 2010
using namespace std;

int sg( double x ) { return (x>-eps)-(x<eps); }
struct Vector {
    double x, y;
    Vector(){}
    Vector( double x, double y ):x(x),y(y){}
    Vector operator+( const Vector & b ) const { return Vector(x+b.x,y+b.y); }
    Vector operator-( const Vector & b ) const { return Vector(x-b.x,y-b.y); }
    Vector operator*( double b ) const { return Vector(x*b,y*b); }
    Vector operator/( double b ) const { return Vector(x/b,y/b); }
    double operator^( const Vector & b ) const { return x*b.y-y*b.x; }
    double operator&( const Vector & b ) const { return x*b.x+y*b.x; }
    bool operator<( const Vector & b ) const {
        return x<b.x || (x-b.x<eps && y<b.y);
    }
};
typedef Vector Point;

bool onleft( Point &A, Point &B, Point &P ) {
    return sg((B-A)^(P-A)) > 0;
}
int convex( int n, Point *p, Point *c ) {
    int m;
    sort( p, p+n );
    c[m=0] = p[0];
    for( int i=1; i<n; i++ ) {
        while( m>0 && !onleft(c[m-1],c[m],p[i]) ) m--;
        c[++m] = p[i];
    }
    int k=m;
    for( int i=n-2; i>=0; i-- ) {
        while( m>k && !onleft(c[m-1],c[m],p[i]) ) m--;
        c[++m] = p[i];
    }
    return m+(n==1);
}
double area( Point &A, Point &B, Point &P ) {
    return (B-A)^(P-A);
}
double maxarea( int n, Point *p ) {
    if( n<=2 ) return 0.0;
    if( n==3 ) return fabs(area(p[0],p[1],p[2]));

    static int nxt[N];
    nxt[n-1]=0;
    for( int i=0; i<n-1; i++ ) nxt[i]=i+1;

    double rt = 0.0;
    for( int i=0; i<n; i++ ) {
        for( int j=nxt[nxt[i]],a=nxt[i],b=nxt[j]; nxt[j]!=i; j=nxt[j] ) {
            while( area(p[i],p[a],p[j])<area(p[i],p[nxt[a]],p[j]) ) a=nxt[a];
            while( area(p[j],p[b],p[i])<area(p[j],p[nxt[b]],p[i]) ) b=nxt[b];
            double ra = area(p[i],p[a],p[j]);
            double rb = area(p[j],p[b],p[i]);
            rt = max( rt, ra+rb );
        }
    }
    return rt/2.0;
}

int n, cn;
Point pts[N], cvx[N];

int main() {
    scanf( "%d", &n );
    for( int i=0; i<n; i++ )
        scanf( "%lf%lf", &pts[i].x, &pts[i].y );
    cn = convex( n, pts, cvx );
    printf( "%.3lf\n", maxarea(cn,cvx) );
}

时间: 2024-10-13 01:22:44

bzoj 1069的相关文章

bzoj 1069 [SCOI2007]最大土地面积(旋转卡壳)

1069: [SCOI2007]最大土地面积 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 2277  Solved: 853[Submit][Status][Discuss] Description 在某块平面土地上有N个点,你可以选择其中的任意四个点,将这片土地围起来,当然,你希望这四个点围成的多边形面积最大. Input 第1行一个正整数N,接下来N行,每行2个数x,y,表示该点的横坐标和纵坐标. Output 最大的多边形面积,答案精确到小

【BZOJ 1069】 [SCOI2007]最大土地面积

1069: [SCOI2007]最大土地面积 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 1677  Solved: 588 [Submit][Status] Description 在某块平面土地上有N个点,你可以选择其中的任意四个点,将这片土地围起来,当然,你希望这四个点围成的多边形面积最大. Input 第1行一个正整数N,接下来N行,每行2个数x,y,表示该点的横坐标和纵坐标. Output 最大的多边形面积,答案精确到小数点后3位.

●BZOJ 1069 [SCOI2007]最大土地面积

题链: http://www.lydsy.com/JudgeOnline/problem.php?id=1069 题解: 计算几何,凸包,旋转卡壳 其实和这个题差不多,POJ 2079 Triangle 把四边形看出两个三角形就好了. 复杂度$O(N^2)$ 代码: #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #

bzoj 1069: [SCOI2007]最大土地面积

先求出凸包,旋转卡壳,可以枚举对角线,再分别找对角线两边最远的点... 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<cstdlib> 6 #include<queue> 7 #define M 100005 8 #define ll long long 9 using namespace std

BZOJ 1069 SCOI 2007 最大土地面积 凸包+旋转卡壳

题目大意:给出平面上的一些点,求其中四个点的最大四边形的面积. 思路:简单yy一下发现这些点肯定都在凸包上,先求个凸包.然后直接暴力肯定是不行的,我们需要一个O(n^2)的做法,比较简单的想法是枚举最后要求的四边形的一条对线,那么这个四边形就被分割成了两个三角形,剩下两个点与这条线组成的三角形的面积和就是答案. 按照旋转卡壳的思想不难发现,这两个点都是单调的.所以枚举对角线然后扫n圈就可以了. CODE: #define _CRT_SECURE_NO_DEPRECATE #include <cm

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

题意:链接 方法:旋转卡壳 解析: 跟POJ2079那个三角形的很像. 所以思路其实也是一个思路. 但是注意到本题是找四边形,如果找三个动点的话好像不太现实. 所以我们枚举对角线的话,对角线上下肯定各有一个点,而且发现下面的点逆时针转动的时候,上面的点其实也是逆时针走. 所以按照旋转卡壳的思想,我们需要枚举一下对角线,再找两个动点更新最大即可. 这个复杂度是O(n^2)->枚举定点以及其对角点,对于本题来说可过. 代码: #include <cmath> #include <cst

【BZOJ】【1069】【SCOI2007】最大土地面积

计算几何/旋转卡壳 从已知点中选出四个使得选出的四边形面积最大,很明显我们应该在凸包上搞. 我一开始的思路是:枚举 i ,找到 i 的对锺点cur1,这两个点将凸包分成了两半,我们在左半中枚举一个 j ,然后在右半中找一个离 j 最远的“对锺点”(可能不是?反正找的是最远……)cur2,然后求cur1和cur2都是单调的,复杂度为枚举 i, j的$O(n^2)$ 然而跪了= =然后我去Orz了proverbs的题解,得到启示:我们可以枚举一条对角线,然后在左半和右半中各找一条跟这条对角线最远的点

【BZOJ】1069: [SCOI2007]最大土地面积(凸包+旋转卡壳)

http://www.lydsy.com/JudgeOnline/problem.php?id=1069 显然这四个点在凸包上,然后枚举两个点找上下最大的三角形即可. 找三角形表示只想到三分QAQ....... 看了题解发现....这是单调的....直接扫...然后,这货叫“旋转卡壳”?是qia还是ka.... 自己一开始写的wa了........然后照标程写,,又wa了.... 后来发现是凸包写渣了QAQ...自己原来的找三角形是没问题的...我好sb..... 可是,为嘛凸包这样写会错. c

BZOJ 1013: [JSOI2008]球形空间产生器sphere

二次联通门 : BZOJ 1013: [JSOI2008]球形空间产生器sphere /* BZOJ 1013: [JSOI2008]球形空间产生器sphere 高斯消元 QAQ SB的我也能终于能秒题了啊 设球心的坐标为(x,y,z...) 那么就可以列n+1个方程,化化式子高斯消元即可 */ #include <cstdio> #include <iostream> #include <cstring> #define rg register #define Max