HDU 2202 && POJ 2079 求平面最大三角形 【旋转卡壳】

HDU - 2202
POJ - 2079

题目大意也说了, 也是一模一样的题意.

思路: 很明显, 这个最大三角形的点一定是在凸包上, O(n^3) 看似不可行, 但是根据数据范围, 实际上极限凸包上最多400个点左右, 但是万一数据范围变动了? 所以用旋转卡壳可以优化到O(n^2), 这样的话已经比较优秀了, 具体做法就是枚举每一条凸包上的边作为底边, 然后动第三个点, 到了临界值时, 在算一次答案即可.

两道题均可AC Code

const int maxn = 5e4+5;
struct point {
    ll x, y;
    friend ll operator * (const point& a,const point& b){
        return a.x*b.y - a.y*b.x;
    }
    bool operator < (const point &_) const {
        if(_.x == x) return y < _.y;
        return x < _.x;
    }
}tb[maxn], po[maxn];
point xl(const point& a, const point& b) {
    return point{b.x-a.x, b.y-a.y};
}
ll dis(point a, point b) {  // 两点之间的距离
    return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y);
}
void solve() {
    int n;
    while(~scanf("%d",&n)) {
        for(int i = 1 ; i <= n ; i ++) {
            scanf("%lld%lld",&po[i].x, &po[i].y);
        }
        sort(po+1, po+n+1);
        int k = 0;
        for(int i = 1 ; i <= n ; i ++) {
            while(k > 1 && xl(tb[k-1], po[i]) * xl(tb[k-1], tb[k]) > 0) --k;
            tb[++k] = po[i];
        }
        int tmp = k;
        for(int i = n - 1 ; i >= 1 ; i --) {
            while(k > tmp && xl(tb[k-1], po[i]) * xl(tb[k-1], tb[k]) > 0) --k;
            tb[++k] = po[i];
        }
        if (n > 1) -- k;
        ll ans = 0;
        for (int i = 1 ; i <= k ; i ++) {
            int t = i%k+1;
            int g = t%k+1;
            while(t != i && g != t) {
                ans = max(ans, xl(tb[i], tb[t]) * xl(tb[i], tb[g]));
                while(xl(tb[i], tb[t]) * xl(tb[i], tb[g]) <
                  xl(tb[i], tb[t]) * xl(tb[i], tb[g%k+1]))
                  g = g%k+1;
                t = t%k+1;
            }
        }
        printf("%.2f\n", 0.5*ans);
    }
}

猜你喜欢

转载自blog.csdn.net/Anxdada/article/details/81390310