zoukankan      html  css  js  c++  java
  • bzoj 1069 [SCOI2007]最大土地面积

    看了黄学长的博客才知道是旋转卡壳的裸题,我似乎是用暴力卡过的

    首先这四个点一定在凸包上,要先把凸包搞出来(忘了判重点WA了一个小时QAQ),

    因为n的范围很小,所以我们可以直接枚举这个四边形的对角线,分别找这条对角线两边的点与这条线组成的最大三角形

    因为是一个凸包所以我们可以三分,但实际上这是有决策单调性的,所以直接上旋转卡壳就可以过了

     1 #define MAXN 4010UL
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <algorithm>
     5 
     6 using namespace std;
     7 
     8 int n, hd, tl, T, num;
     9 double ans;
    10 
    11 struct Point {
    12     double x, y;
    13     friend double operator * (Point a, Point b) {
    14         return a.x*b.y-a.y*b.x;
    15     }
    16     friend Point operator - (Point a, Point b) {
    17         return (Point){a.x-b.x, a.y-b.y};
    18     }
    19     friend bool operator < (Point a, Point b) {
    20         return a.x==b.x?a.y<b.y:a.x<b.x;
    21     }
    22 }pt[MAXN<<1], q[MAXN<<1];
    23 
    24 bool Check(Point a, Point b) {
    25     return a*b<=0;
    26 }
    27 
    28 double F(Point a, Point b, Point c) {
    29     
    30     return fabs(a*b+b*c+c*a)/2.;
    31 }
    32 
    33 int Solve(Point a, Point b, int l, int r) {
    34     ++ num;
    35     double ret = -1.;
    36     int pos;
    37     while(r-l>=3) {++ T;
    38         int mid = (l+r)>>1, midd = (mid+r)>>1;
    39         if(F(a, b, pt[mid])>F(a, b, pt[midd])) r = midd-1;
    40         else l = mid+1;
    41     }
    42     for(int i = l ; i <= r ; ++ i) {
    43         double w = F(a, b, pt[i]);
    44         if(ret<w) ret = w, pos = i;
    45     }
    46     return pos;
    47 }
    48 
    49 int main() {    
    50     scanf("%d", &n);
    51     for(int i = 1 ; i <= n ; ++ i) scanf("%lf%lf", &pt[i].x, &pt[i].y);
    52     sort(pt+1, pt+n+1);
    53     for(int i = 1 ; i <= n ; ++ i) {
    54         while(hd+1<tl&&Check(q[tl-1]-q[tl-2], pt[i]-q[tl-1])) -- tl;
    55         q[tl ++] = pt[i];
    56     }
    57     for(int i = n-1 ; i >= 2 ; -- i) {
    58         while(hd+1<tl&&Check(q[tl-1]-q[tl-2], pt[i]-q[tl-1])) -- tl;
    59         q[tl ++] = pt[i];
    60     }
    61     while(hd+1<tl&&Check(q[tl-1]-q[tl-2], q[hd]-q[tl-1])) -- tl;
    62     int ti = 0;
    63     for(int i = hd ; i < tl ; ++ i) ++ ti, pt[ti] = q[i], pt[ti+tl-hd] = q[i];
    64     for(int i = 1 ; i <= ti ; ++ i) {
    65         int lt1 = 0, lt2 = 0;
    66         for(int j = i+2 ; j <= ti ; ++ j) if(j-i>=2&&i+ti-j>=2) {
    67             lt1 = Solve(pt[i], pt[j], i+1, j-1), lt2 = Solve(pt[i], pt[j], j+1, i+ti-1);
    68             double w = F(pt[i], pt[j], pt[lt1])+F(pt[i], pt[j], pt[lt2]);
    69             if(ans<w) ans = w;
    70         }
    71     }
    72     printf("%.3lf", ans);
    73     return 0;
    74 }
    View Code
  • 相关阅读:
    第三周学习进度表
    思维导图
    第二周学习进度表
    调查问卷
    微感想
    C/C++数组取值的真实实现——一个初学者的常见疑惑
    保存所有标签页,以便下次打开继续工作
    内存越界调到心态爆炸
    C语言VC6的一个asprintf实现,或:VC6上C语言使用asprintf, snprintf的坑
    Learning and Inference for Hierarchically Split PC中文字幕
  • 原文地址:https://www.cnblogs.com/assassain/p/5437671.html
Copyright © 2011-2022 走看看