• UVA10173 Smallest Bounding Rectangle 最小面积矩形覆盖


    (color{#0066ff}{题目描述})

    给定n(>0)二维点的笛卡尔坐标,编写一个程序,计算其最小边界矩形的面积(包含所有给定点的最小矩形)。

    输入文件可以包含多个测试样例。每个测试样例从包含一个正数的行开始。 整数N(<1001),表示该测试样例中的点的数量。接下来的n行各包含两个实数,分别给出一个点的x和y坐标。输入最后包含一个值为0的测试样例,该值必须不被处理。

    对于输入中的每个测试样例都输出一行,包含最小边界矩形的面积,小数点后四舍五入到第四位。

    (color{#0066ff}{输入格式})

    (color{#0066ff}{输出格式})

    (color{#0066ff}{输入样例})

    3
    -3.000 5.000
    7.000 9.000
    17.000 5.000
    4
    10.000 10.000
    10.000 20.000
    20.000 20.000
    20.000 10.000
    0
    

    (color{#0066ff}{输出样例})

    80.0000
    100.0000
    

    (color{#0066ff}{数据范围与提示})

    none

    (color{#0066ff}{题解})

    旋转卡壳

    首先先求一遍凸包

    对于最小面积外接矩形,显然至少有一条边与凸包重合,就枚举那条边(底边)

    对于上面的边,通过叉积叉出面积判断最高位置,找到上边

    对于左边,用点积,找到最大点积(投影最长,那么最靠左),右边指针从左边开始找投影最短

    每次移动底边,然后更新上左右,来更新ans

    #include <bits/stdc++.h>
    #define _ 0
    #define LL long long
    inline LL in() {
        LL x = 0, f = 1; char ch;
        while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
        while(isdigit(ch)) x = x * 10 + (ch ^ 48), ch = getchar();
        return x * f;
    }
    
    struct node {
        double x,y;
        node(double x = 0, double y = 0):x(x), y(y) {}
        node operator - (const node &b) const {
            return node(x - b.x, y - b.y);
        }
        double operator ^ (const node &b) const {
            return x * b.y - y * b.x;
        }
        double operator * (const node &b) const {
            return x * b.x + y * b.y;
        }
        double mo() {
            return sqrt(x * x + y * y);
        }
        double jj() const {
            return atan2(y, x);
        }
    };
    const int maxn = 10005;
    node e[maxn], v[maxn];
    int n,top;
    
    double S(node a,node b,node c) {
        return (b - a) ^ (c - a);
    }
    
    bool cmp(const node &a, const node &b) {
        return (a.jj() < b.jj() || (a.jj() == b.jj() && (a - e[0]).mo() < (b - e[0]).mo()));
    }
    void tubao() {
        int min = 0;
        for(int i = 0; i < n; i++) 
            if(e[i].y < e[min].y || (e[i].y == e[min].y && e[i].x < e[min].x)) min = i;
        std::swap(e[0], e[min]);
        for(int i = 1; i < n; i++) e[i] = e[i] - e[0];
        e[0] = 0;
        std::sort(e + 1, e + n, cmp);
        v[0] = e[0], v[1] = e[1];
        for(int i = top = 2; i < n; i++) {
            while((top > 1) && (S(v[top - 2], v[top - 1], e[i]) <= 0)) top--;
            v[top++] = e[i];
        }
        v[top] = e[0];
    }
    
    double C(node a,node b,node c) {
        return (c - a) * (b - a);
    }
    
    double rotate()
    {
        if(top < 3) return 0;
        int l = 1, u = 1, r;
        double a, b, c, ans = 1e20;
        for(int i = 0; i < top; i++) {
            while(S(v[i], v[i + 1], v[u + 1]) > S(v[i], v[i + 1], v[u])) u = (u + 1) % top;
            while(C(v[i], v[i + 1], v[l + 1]) > C(v[i], v[i + 1], v[l])) l = (l + 1) % top;
            if(!i) r = l;
            while(C(v[i], v[i + 1], v[r + 1]) <= C(v[i], v[i + 1], v[r])) r = (r + 1) % top;
            a = S(v[i], v[i + 1], v[u]);
            b = C(v[i], v[i + 1], v[l]) - C(v[i], v[i + 1], v[r]);
            c = C(v[i], v[i + 1], v[i + 1]);
            ans = std::min(ans, a * b / c);
        }
        return ans;
    }
    
    int main() {
        while("fuck") {
            n = in();
            if(!n) break;
            for(int i = 0; i < n; i++) scanf("%lf%lf", &e[i].x, &e[i].y);
            tubao();
            printf("%.4lf
    ", rotate());
        }
        return 0;
    }
    
  • 相关阅读:
    session监听
    Ubuntu上安装MongoDB(转)
    JAVA中的集合(转)
    Iterator的用法(转)
    PHPExcel常用方法汇总(转)
    MongoDB的安装及在PHP中的配置Windows版
    [转载]使用FastReport 3.0及以上版本创建动态报表的几个技巧
    FastReport
    ZeosLib
    [转载]FastReport问题整理
  • 原文地址:https://www.cnblogs.com/olinr/p/10197359.html
Copyright © 2020-2023  润新知