UVa 10652 Board Wrapping

题意是给定一些矩形,用一条线包围所有的矩形,同时要求包围的面积最小。

思路

凸包

实质就是自己算出所有矩形的四个顶点,求凸包,然后求面积即可。

#include <vector>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <map>
#include <set>
#include <algorithm>

using namespace std;
const double eps = 1e-10;
const double PI = 3.1415926535898;

double add(double a, double b){
    //if(abs(a + b) < eps * (abs(a) + abs(b))) return 0;
    return a + b;
}

struct P{
    double x, y;
    P(){}
    P(double x, double y) : x(x), y(y) {}
    P operator + (P p){
        return P(add(x, p.x), add(y, p.y));
    }
    P operator - (P p){
        return P(add(x, -p.x), add(y, -p.y));
    }
    P operator * (double d){
        return P(x * d, y * d);
    }
    double dot(P p){
        return add(x * p.x, y * p.y);
    }
    double det(P p){
        return add(x * p.y, -y * p.x);
    }
};

bool cmp_x(const P & p, const P & q){
    if(p.x != q.x) return p.x < q.x;
    return p.y <q.y;
}
vector<P> convex_hull(P* ps, int n){
    sort(ps, ps + n, cmp_x);
    int k = 0;
    vector<P> qs(n * 2);
    for(int i = 0; i < n; ++i){
        while(k > 1 && (qs[k - 1] - qs[k - 2]).det(ps[i] - qs[k - 1]) <= 0) k--;
        qs[k++] = ps[i];
    }
    for(int i = n - 2, t = k; i >= 0; i --){
        while(k > t && (qs[k - 1] - qs[k - 2]).det(ps[i] - qs[k - 1]) <= 0) k--;
        qs[k++] = ps[i];
    }
    qs.resize(k - 1);
    return qs;
}

const int maxn = 10000 + 10;
P ps[5 * maxn];

double solve(int cnt, int n){
    vector<P> qs = convex_hull(ps, cnt);
    double sum = 0.00;
    int len = qs.size();
    for(int i = 1; i < len - 1; ++i){
        sum += (qs[i] - qs[0]).x * (qs[i + 1] - qs[0]).y - (qs[i + 1] - qs[0]).x * (qs[i] - qs[0]).y;
    }
    sum /= 2.0;
    return fabs(sum);
}

void Build(double x, double y, double w, double h, double u, int & cnt){
    ps[cnt].x = x - w * cos(u) - h * sin(u);
    ps[cnt++].y = y + w * sin(u) - h * cos(u);
    ps[cnt].x = x - w * cos(u) + h * sin(u);
    ps[cnt++].y = y + w * sin(u) + h * cos(u);
    ps[cnt].x = x + w * cos(u) + h * sin(u);
    ps[cnt++].y = y - w * sin(u) + h * cos(u);
    ps[cnt].x = x + w * cos(u) - h * sin(u);
    ps[cnt++].y = y - w * sin(u) - h * cos(u);
}

int main()
{
    int T; scanf("%d", &T);
    while(T --){
        memset(ps, 0, sizeof(ps));
        int n; scanf("%d", &n);
        int cnt = 0;
        double sum = 0;
        for(int i = 0; i < n; ++i){
            double x, y, u, w, h;
            scanf("%lf%lf%lf%lf%lf", &x, &y, &w, &h, &u);
            u = u * PI / 180;
            sum += w * h;
            Build(x, y, w / 2, h / 2, u, cnt);
        }
        printf("%.1f %%\n", sum * 100 / solve(cnt, n));
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值