本题是很不错的凸包题目:考查向量的旋转,求凸包,求凸包的面积。
今天是儿童节的第三题。
#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 %
**/