uva 10652 Board Wrapping

本题是很不错的凸包题目:考查向量的旋转,求凸包,求凸包的面积。

今天是儿童节的第三题。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 2500;
const double pi = acos(-1);
double area1 = 0, area2 = 0;
int n;

struct point {
    double x;
    double y;
    point(double a = 0, double b = 0):x(a), y(b) {}
};
typedef point Vector;
vector <point> v(2500);//保存处理后的点。

point operator - (const point &a, const point &b) {
    return point(a.x-b.x, a.y-b.y);
}
point operator + (const point &a, const point &b) {
    return point(a.x+b.x, a.y+b.y);
}
const double eps = 1e-10;
int dcmp(double x) {
    if(fabs(x)<eps) return 0;
    if(x > 0 ) return 1;
    return -1;
}

double det(const point &a, const point &b) {
    return a.x*b.y - a.y*b.x;
}
// get convex_hull;
struct polygon_convex {
    vector <point> P;
    polygon_convex(int Size = 0) {
        P.resize(Size);
    }
};

bool comp_less(const point &a, const point &b) {
    return dcmp(a.x-b.x)<0 || (dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)<0);
}
bool cmpx(const point &a, const point &b) {
    if(dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0)
        return true;
    return false;
}
polygon_convex convex_hull(vector<point> a) {
    polygon_convex res(2*a.size()+5);
    sort(a.begin(), a.end(), comp_less);
    a.erase(unique(a.begin(), a.end(), cmpx), a.end());
    int m = 0;
    for(int i = 0; i < (int)a.size(); ++i) {
        while(m>1 && dcmp(det(res.P[m-1]-res.P[m-2], a[i]-res.P[m-2]))<=0)
            --m;
            res.P[m++] = a[i];
    }
    int k = m;
    for(int i = int(a.size())-2; i >= 0; --i) {
        while(m>k && dcmp(det(res.P[m-1]-res.P[m-2], a[i]-res.P[m-2]))<=0)
            --m;
        res.P[m++] = a[i];
    }
    res.P.resize(m);
    if(a.size()>1) res.P.resize(m-1);
    return res;
}
//get convex_hull;

Vector Rotate(Vector A, double rad) {
    return Vector(A.x*cos(rad)-A.y*sin(rad), A.x*sin(rad)+A.y*cos(rad));
}

double torad(double x) {
    return x*pi/180;
}

void input() {
    scanf("%d", &n);
    point A, B, C, D;//代表旋转后矩形的四个顶点。
    for(int i = 0; i < n; i++) {
        double x, y, w, h, j, ang;
        scanf("%lf%lf%lf%lf%lf", &x, &y, &w, &h, &j);
        point o(x,y);//矩形中心点。
        ang = -torad(j);//将度转为弧度.
        A = o + Rotate(Vector(-w/2, -h/2), ang);
        B = o + Rotate(Vector(w/2, -h/2), ang);
        C = o + Rotate(Vector(-w/2, h/2), ang);
        D = o + Rotate(Vector(w/2, h/2), ang);
        v.push_back(A);
        v.push_back(B);
        v.push_back(C);
        v.push_back(D);
        area1 += w*h;
    }
}

void init() {
    area1 = 0;
    area2 = 0;
    v.clear();
}
//求凸包的面积.
double polygonArea(vector<point> a, int n) {
    double area = 0;
    for(int i = 1; i < n-1; i++) {
        area += det(a[i]-a[0], a[i+1]-a[0]);
    }
    return area/2;
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T--) {
        init();
        input();
        polygon_convex tres = convex_hull(v);
        area2 = polygonArea(tres.P, tres.P.size());
        printf("%.1lf %%\n", area1*100/area2);
    }
    return 0;
}
/**
input:
1
4
4 7.5 6 3 0
8 11.5 6 3 0
9.5 6 6 3 90
4.5 3 4.4721 2.2361 26.565
output:
63.4 %
**/

你可能感兴趣的:(uva 10652 Board Wrapping)