zoukankan      html  css  js  c++  java
  • 【洛谷 P4166】 [SCOI2007]最大土地面积(凸包,旋转卡壳)

    题目链接
    又调了我两个多小时巨亏
    直接(O(n^4))枚举4个点显然不行。
    数据范围提示我们需要一个(O(n^2))的算法。
    于是(O(n^2))枚举对角线,然后在这两个点两边各找一个点使其和对角线构成的三角形面积最大,也就是叉积的绝对值最大。显然具有单调性,于是旋转卡壳维护。

    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    const int MAXN = 50010;
    const double eps = 1e-8;
    struct point{
        double x, y;
    }p[MAXN];
    inline double sig(double x){
    	return (x > eps) - (x < -eps);
    }
    int operator == (point a, point b){
    	return a.x == b.x && a.y == b.y;
    }
    double operator * (point a, point b){    // a x b
        return a.x * b.y - b.x * a.y;
    }
    point operator - (point a, point b){     // a - b
        return (point){ a.x - b.x, a.y - b.y };
    }
    point operator + (point a, point b){     // a + b
        return (point){ a.x + b.x, a.y + b.y };
    }
    int cmp(const point a, const point b){   
        return a.x == b.x ? a.y < b.y : a.x < b.x;
    }
    inline int judge(point a, point b, point c){    //Kab > Kac
    	return (b.y - a.y) * (c.x - a.x) >= (c.y - a.y) * (b.x - a.x); 
    }
    inline double calc(point a, point b, point c){
    	return fabs((b - a) * (c - a));
    }
    int n, top, tp;
    point st[MAXN], ts[MAXN];
    double ans = 0;
    int main(){
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i)
           scanf("%lf%lf", &p[i].x, &p[i].y);
        sort(p + 1, p + n + 1, cmp);
        st[0] = (point){2434321, 2515215};
        for(int i = 1; i <= n; ++i){
           if(p[i] == st[top]) continue;
           while(top > 1 && judge(st[top - 1], st[top], p[i])) --top;
           st[++top] = p[i];
        }
        for(int i = 1; i <= n; ++i){
           if(p[i] == ts[tp]) continue;
    	   while(tp > 1 && !judge(ts[tp - 1], ts[tp], p[i])) --tp;
           ts[++tp] = p[i];
        }
        for(int i = tp - 1; i; --i) st[++top] = ts[i];
        st[0] = st[--top];
        for(int i = 1; i < top; ++i){
        	int k = i + 1, l = (i + 3) % top;
        	for(int j = i + 2; j <= top; ++j){
        	   while(sig(calc(st[i], st[j], st[k]) - calc(st[i], st[j], st[k + 1])) < 0) if(++k > top) k = 1;
        	   while(sig(calc(st[i], st[j], st[l]) - calc(st[i], st[j], st[l + 1])) < 0) if(++l > top) l = 1;
        	   ans = max(ans, (calc(st[i], st[j], st[k]) + calc(st[i], st[j], st[l])));
            }
        }
        printf("%.3lf
    ", ans / 2);
        return 0;
    }
    
  • 相关阅读:
    iframe
    # ? & 号在url中的的作用
    面向对象和面向过程
    dom
    DOM对象与jquery对象有什么不同
    绑定js
    leetcode — search-for-a-range
    leetcode — search-for-a-range
    leetcode — search-in-rotated-sorted-array
    leetcode — longest-valid-parentheses
  • 原文地址:https://www.cnblogs.com/Qihoo360/p/10325700.html
Copyright © 2011-2022 走看看