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