#include<bits/stdc++.h>#definexfirst#defineysecondusingnamespace std;constint N =1e5+5;constdouble pi =acos(-1), eps =1e-8;typedef pair<int,int> PII;typedef pair<double,double> PDD;intsign(double x){if(fabs(x)< eps)return0;if(x <0)return-1;return1;}intcmp(double x,double y){if(fabs(x - y)< eps)return0;if(x < y)return-1;return1;}structPoint{double x, y;Point(double x =0,double y =0):x(x),y(y){}booloperator<(const Point &p){if(x == p.x)return y < p.y;return x < p.x;}
Point operator+(Point a){returnPoint(x + a.x, y + a.y);}
Point operator-(Point a){returnPoint(x - a.x, y - a.y);}
Point operator*(double t){returnPoint(x * t, y * t);}
Point operator/(double t){returnPoint(x / t, y / t);}booloperator==(Point a){return x == a.x && y == a.y;}doublelenth(){//模returnsqrt(x * x + y * y);}};structLine{
Point st, ed;Line(){}Line(Point a, Point b){this->st = a;this->ed = b;}};structCircle{
Point p;double r;Circle(){}Circle(Point p,double r){this->p = p;this->r = r;}};doubleget_dist(Point a, Point b){//两点距离double dx = a.x - b.x;double dy = a.y - b.y;returnsqrt(dx * dx + dy * dy);}doubleget_angle_line(const Line &a){//线的角度returnatan2(a.ed.y - a.st.y, a.ed.x - a.st.x);}doubledot(Point a, Point b){//点积return a.x * b.x + a.y * b.y;}doublecross(Point a, Point b){//叉积return a.x * b.y - b.x * a.y;}doubleget_angle(Point a, Point b){//两向量夹角returnacos(dot(a, b)/ a.lenth()/ b.lenth());}doublearea(Point a, Point b, Point c){returncross(b - a, c - a);}
Point norm(Point a){//单位向量return a / a.lenth();}
Point rotate(Point a,double angle){//点的旋转returnPoint(a.x *cos(angle)+ a.y *sin(angle),-a.x *sin(angle)+ a.y *cos(angle));}
Point get_line_intersection(Point p, Point v, Point q, Point w){//两直线交点
Point u = p - q, res;double t =cross(w, u)/cross(v, w);return{p.x + v.x * t, p.y + v.y * t};}
Point get_line_intersection(Line a, Line b){//两直线交点returnget_line_intersection(a.st, a.ed - a.st, b.st, b.ed - b.st);}boolon_right(Line &a, Line &b, Line &c){//bc的交点是否在a的右侧auto o =get_line_intersection(b, c);returnsign(area(a.st, a.ed, o))<=0;}doubledistance_to_line(Point p, Point a, Point b){//点到线的距离
Point v1 = b - a, v2 = p - a;returnfabs(cross(v1, v2)/ v1.lenth());}doubledistance_to_segment(Point p, Point a, Point b){//点到线段的距离if(a == b)return(p - a).lenth();
Point v1 = b - a, v2 = p - a, v3 = p - b;if(sign(dot(v1, v2))<0)return v2.lenth();if(sign(dot(v1, v3))>0)return v3.lenth();returndistance_to_line(p, a, b);}
Point get_line_projection(Point p, Point a, Point b){//点在线上的投影
Point v = b - a;return a + v *(dot(v, p - a)/dot(v, v));}doubleproject(Point a, Point b, Point c){//ac在ab上的投影returndot(b - a, c - a)/(b - a).lenth();}boolon_segment(Point p, Point a, Point b){//点是否在线段上returnsign(cross(p - a, p - b))==0&&sign(dot(p - a, p - b))<=0;}boolsegment_intersection(Point a1, Point a2, Point b1, Point b2){//线段是否相交double c1 =cross(a2 - a1, b1 - a1), c2 =cross(a2 - a1, b2 - a1);double c3 =cross(b2 - b1, a2 - b1), c4 =cross(b2 - b1, a1 - b1);returnsign(c1)*sign(c2)<=0&&sign(c3)*sign(c4)<=0;}boolcmp_line(const Line &a,const Line &b){//线段按角度排序double A =get_angle_line(a), B =get_angle_line(b);if(!cmp(A, B))returnarea(a.st, a.ed, b.ed)<0;return A < B;}
Point a[N], ans[N], r;
Line line[N];
Circle cir[N];
PII A[N];
PDD D[N];double res, R;int stk[N], top, n, q[N], cnt, m;bool used[N];doublepolygon_area(){//多边形面积double res =0;for(int i =0; i < n; i ++) res +=cross(a[i], a[(i +1)% n]);returnfabs(0.5* res);}voidandrew(){//求凸包sort(a, a + n);for(int i =0; i < n; i ++){while(top >=2&&area(a[stk[top -1]], a[stk[top]], a[i])<=0){if(area(a[stk[top -1]], a[stk[top]], a[i])<0){
used[stk[top --]]=0;}else{
top --;}}
stk[++ top]= i;
used[i]=1;}
used[0]=0;for(int i = n -1;~i; i --){if(used[i])continue;while(top >=2&&area(a[stk[top -1]], a[stk[top]], a[i])<=0) top --;
stk[++ top]= i;}}doublerotating_calipers(){//旋转卡壳if(top <=3)returnget_dist(a[0], a[n -1]);double res =0;for(int i =1, j =3; i <= top; i ++){auto d = a[stk[i]], e = a[stk[i +1]];while(area(d, e, a[stk[j]])<area(d, e, a[stk[j +1]])){
j =(j +1)% top;if(!j) j =1;}
res =max(res,max(get_dist(d, a[stk[j]]),get_dist(e, a[stk[j]])));}return res;}doublehalf_plane_intersection(){//半平面交sort(line, line + cnt, cmp_line);int hh =0, tt =-1;for(int i =0; i < cnt; i ++){if(i &&!cmp(get_angle_line(line[i]),get_angle_line(line[i -1])))continue;while(hh +1<= tt &&on_right(line[i], line[q[tt -1]], line[q[tt]])) tt --;while(hh +1<= tt &&on_right(line[i], line[q[hh]], line[q[hh +1]])) hh ++;
q[++ tt]= i;}while(hh +1<= tt &&on_right(line[q[hh]], line[q[tt -1]], line[q[tt]])) tt --;while(hh +1<= tt &&on_right(line[q[tt]], line[q[hh]], line[q[hh +1]])) hh ++;
q[++ tt]= q[hh];int k =0;for(int i = hh; i < tt; i ++) ans[k ++]=get_line_intersection(line[q[i]], line[q[i +1]]);double res =0;for(int i =1; i +1< k; i ++) res +=area(ans[0], ans[i], ans[i +1]);return res /2;}
Line get_line(Point a, Point b){returnLine((a + b)/2,rotate(b - a, pi /2));}doubleget_circle_line_intersection(Point a, Point b, Point &pa, Point &pb){//圆与直线交点auto e =get_line_intersection(a, b - a, r,rotate(b - a, pi /2));auto mind =get_dist(r, e);if(!on_segment(e, a, b)) mind =min(get_dist(r, a),get_dist(r, b));if(cmp(R, mind)<=0)return mind;auto len =sqrt(R * R -get_dist(r, e)*get_dist(r, e));
pa = e +norm(a - b)* len;
pb = e +norm(b - a)* len;return mind;}doubleget_sector(Point a, Point b){//扇形面积auto angle =acos(dot(a, b)/ a.lenth()/ b.lenth());if(sign(cross(a, b))<0) angle =-angle;return R * R * angle /2;}doubleget_circle_triangle_area(Point a, Point b){//三角剖分 圆与三角面积交auto da =get_dist(r, a), db =get_dist(r, b);if(cmp(R, da)>=0&&cmp(R, db)>=0)returncross(a, b)/2;if(!sign(cross(a, b)))return0;
Point pa, pb;auto mind =get_circle_line_intersection(a, b, pa, pb);if(cmp(R, mind)<=0)returnget_sector(a, b);if(cmp(R, da)>=0)returncross(a, pb)/2+get_sector(pb, b);if(cmp(R, db)>=0)returnget_sector(a, pa)+cross(pa, b)/2;returnget_sector(a, pa)+cross(pa, pb)/2+get_sector(pb, b);}
Circle get_circle(Point a, Point b, Point c){//三点求圆auto u =get_line(a, b), v =get_line(a, c);auto p =get_line_intersection(u.st, u.ed, v.st, v.ed);returnCircle(p,get_dist(p, a));}
Circle min_circle_cover(){//最小圆覆盖random_shuffle(a, a + n);
Circle c =Circle(a[0],0);for(int i =1; i < n; i ++){if(cmp(c.r,get_dist(c.p, a[i]))<0){
c ={a[i],0};for(int j =0; j < i; j ++){if(cmp(c.r,get_dist(c.p, a[j]))<0){
c ={(a[i]+ a[j])/2,get_dist(a[i], a[j])/2};for(int k =0; k < j; k ++){if(cmp(c.r,get_dist(c.p, a[k]))<0){
c =get_circle(a[i], a[j], a[k]);}}}}}}return c;}doublef(double x){//辛普森积分函数(圆的面积并)int cnt =0;for(int i =0; i < n; i ++){auto X =fabs(x - cir[i].p.x), R = cir[i].r;if(cmp(X, R)<0){auto Y =sqrt(R * R - X * X);
a[cnt ++]={cir[i].p.y - Y, cir[i].p.y + Y};}}if(!cnt)return0;sort(a, a + cnt);double res =0, st = a[0].x, ed = a[0].y;for(int i =1; i < cnt; i ++){if(a[i].x <= ed){
ed =max(ed, a[i].y);}else{
res += ed - st;
st = a[i].x, ed = a[i].y;}}return res + ed - st;}doublesimpson(double l,double r){//辛普森积分auto mid =(l + r)/2;return(r - l)*(f(l)+4*f(mid)+f(r))/6;}doubleasr(double l,double r,double s){//自适应auto mid =(l + r)/2;auto left =simpson(l, mid), right =simpson(mid, r);if(fabs(s - left - right)< eps)return left + right;returnasr(l, mid, left)+asr(mid, r, right);}signedmain(){}
三维计算几何
#include<bits/stdc++.h>usingnamespace std;constint N =1e4+5;constdouble eps =1e-12;int n, m;bool g[N][N];double res;doublerand_eps(){return((double)rand()/ RAND_MAX -0.5)* eps;}structPoint{double x, y, z;voidshake(){
x +=rand_eps(), y +=rand_eps(), z +=rand_eps();}
Point operator-(Point t){return{x - t.x, y - t.y, z - t.z};}doubleoperator&(Point t){return x * t.x + y * t.y + z * t.z;}
Point operator*(Point t){return{y * t.z - t.y * z, z * t.x - x * t.z, x * t.y - y * t.x};}doublelen(){returnsqrt(x * x + y * y + z * z);}};
Point q[N];structPlane{int v[3];
Point norm(){// 法向量return(q[v[1]]- q[v[0]])*(q[v[2]]- q[v[0]]);}doublearea(){// 求面积returnnorm().len()/2;}boolabove(Point a){return((a - q[v[0]])&norm())>=0;}};
Plane plane[N], np[N];voidget_convex_3d(){//三维凸包
plane[m ++]={0,1,2};
plane[m ++]={2,1,0};for(int i =3; i < n; i ++){int cnt =0;for(int j =0; j < m; j ++){bool t = plane[j].above(q[i]);if(!t) np[cnt ++]= plane[j];for(int k =0; k <3; k ++) g[plane[j].v[k]][plane[j].v[(k +1)%3]]= t;}for(int j =0; j < m; j ++){for(int k =0; k <3; k ++){int a = plane[j].v[k], b = plane[j].v[(k +1)%3];if(g[a][b]&&!g[b][a]) np[cnt ++]={a, b, i};}}
m = cnt;for(int j =0; j < m; j ++) plane[j]= np[j];}}signedmain(){
cin >> n;for(int i =0; i < n; i ++){
cin >> q[i].x >> q[i].y >> q[i].z;
q[i].shake();}get_convex_3d();for(int i =0; i < m; i ++) res += plane[i].area();printf("%lf", res);}