码迷,mamicode.com
首页 > 其他好文 > 详细

凸包(BZOJ1069)

时间:2016-12-23 23:00:28      阅读:217      评论:0      收藏:0      [点我收藏+]

标签:can   div   优秀   turn   blog   tor   struct   bool   ++   

顶点一定在凸包上,我们枚举对角线,观察到固定一个点后,随着另一个点的增加,剩下两个点的最优位置一定是单调的,于是就得到了一个优秀的O(n^2)做法。

#include <cstdio>
#include <algorithm>

const int N = 2005;
int n,r,p1,p2,q[N];
double ans;
struct nd {
    double x,y;
    bool operator < (const nd &b) const {return x == b.x ? y < b.y : x < b.x;}
    nd operator - (const nd &b) const {return (nd){x-b.x,y-b.y};}
    double operator * (const nd &b) const {return x*b.y-y*b.x;}
}a[N];
double cj(int x, int y, int z) {return (a[x]-a[y])*(a[z]-a[y]);}

int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) scanf("%lf%lf", &a[i].x, &a[i].y);
    std::sort(a+1, a+1+n);
    for(int i = 1; i <= n; i++) {
        while(r > 1 && cj(q[r], q[r-1], i) >= 0) r--;
        q[++r] = i;
    }
    int rr = r;
    for(int i = n-1; i >= 1; i--) {
        while(r > rr && cj(q[r], q[r-1], i) >= 0) r--;
        q[++r] = i;
    }
    for(int i = 1; i < r; i++) printf("%.0f %.0f\n", a[q[i]].x, a[q[i]].y);
    for(int i = 1; i < r; i++) {
        int p1 = i+1, p2 = i+3;
        for(int j = i+2; j < r-1; j++) {
            while(p1 < j-1 && cj(q[j],q[i],q[p1]) <= cj(q[j],q[i],q[p1+1])) p1++;
            while(p2 <= j || (p2 < r-1 && cj(q[p2],q[i],q[j]) <= cj(q[p2+1],q[i],q[j]))) p2++;
            ans = std::max(ans, cj(q[j],q[i],q[p1])+cj(q[p2],q[i],q[j]));
        }
    }
    printf("%.3f", ans/2);
    return 0;
}

凸包(BZOJ1069)

标签:can   div   优秀   turn   blog   tor   struct   bool   ++   

原文地址:http://www.cnblogs.com/juruolty/p/6216118.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!