#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>
#include <complex>
#include <set>
using namespace std;

#define EPS 1e-7

typedef long long LL;

typedef complex<double> P;
typedef const P &rP;

struct v3d{
	double x, y, z;

	v3d operator- (const v3d &v) const{
		return (v3d){x - v.x, y - v.y, z - v.z};
	}
	
	operator P() const{
		return P(x, y);
	}

	v3d rot(double txy, double tyz){
		P a = P(x, y) * polar(1.0, txy);
		P b = P(imag(a), z) * polar(1.0, tyz);
		return (v3d){real(a), real(b), imag(b)};
	}
};

inline double dot(const v3d &a, const v3d &b){
	return a.x * b.x + a.y * b.y + a.z * b.z;
}

inline v3d cross(const v3d &a, const v3d &b){
	return (v3d){
		a.y * b.z - a.z * b.y,
		a.z * b.x - a.x * b.z,
		a.x * b.y - a.y * b.x
	};
}

inline double norm(const v3d &v){
	return dot(v, v);
}


struct comparer{
	bool operator() (rP a, rP b){
		if(real(a) != real(b)) return real(a) < real(b);
		return imag(a) < imag(b);
	}
};

inline double dot(rP a, rP b){
	return real(a) * real(b) + imag(a) * imag(b);
}

inline double cross(rP a, rP b){
	return real(a) * imag(b) - imag(a) * real(b);
}

int ccw(P a, P b, P c) {
	b -= a; c -= a;
	if (cross(b, c) > 0)	 return +1;	
	if (cross(b, c) < 0)	 return -1;	
	if (dot(b, c) < 0)		 return +2;	
	if (norm(b) < norm(c)) return -2;
	return 0;
}

vector<P> convex_hull(vector<P> ps) {
	int n = ps.size(), k = 0;
	sort(ps.begin(), ps.end(), comparer());
	vector<P> ch(2*n);
	for (int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull
		while (k >= 2 && ccw(ch[k-2], ch[k-1], ps[i]) <= 0) --k;
	for (int i = n-2, t = k+1; i >= 0; ch[k++] = ps[i--]) // upper-hull
		while (k >= t && ccw(ch[k-2], ch[k-1], ps[i]) <= 0) --k;
	ch.resize(k-1);
	return ch;
}

double square(const vector<P> &v){
	double s = 0.0;
	for(int i = 2; i < v.size(); ++i){
		s += cross(v[i] - v[0], v[i-1] - v[0]);
	}
	return abs(s) * 0.5;
}

vector<v3d> cor;
set<LL> st;

inline bool check(int a, int b, int c){
	if(a == b || b == c || c == a) return true;
	v3d v1 = cor[b] - cor[a], v2 = cor[c] - cor[a];
	return norm(cross(v1, v2)) > EPS || dot(v1, v2) > EPS;
}


double calc(int a, int b, int c){
	int n = cor.size();
	v3d nv = cross(cor[b] - cor[a], cor[c] - cor[a]);
	int t = 0;
	LL S = 0;
	vector<int> pt;
	for(int i = 0; i < n && t != 3; ++i){
		double g = dot(cor[i] - cor[a], nv);
		if( g > EPS ){
			t |= 1;
		}
		else if( g < -EPS ){
			t |= 2;
		}
		else{
			pt.push_back(i);
			S |= 1LL << i;
		}
	}

	if(t == 3 || !st.insert(S).second) return 0.0;

	double txy = atan2(nv.x, nv.y);
	v3d tmp = nv.rot(txy, 0.0);
	double tyz = atan2(tmp.y, tmp.z);

	vector<P> plane;
	for(int i = 0; i < pt.size(); ++i){
		plane.push_back( (cor[pt[i]] - cor[pt[0]]).rot(txy, tyz) );
	}
	
	return square(convex_hull(plane));
}


int main(){
	int n;
	scanf("%d", &n);
	
	cor.resize(n);
	for(int i = 0; i < n; ++i){
		scanf("%lf%lf%lf", &cor[i].x, &cor[i].y, &cor[i].z);
	}
	
	vector<char> nec(n, 1);
	for(int i = 0; i < n; ++i)
	for(int j = 0; j < n && nec[i]; ++j)
	for(int k = 0; k < n; ++k){
		if(!check(i, j, k)){
			nec[i] = 0;
			break;
		}
	}

	for(int i = 0; i < n; ){
		if(nec[i]){
			++i;
		}
		else{
			cor[i] = cor[--n];
			nec[i] = nec[n];
		}
	}

	cor.resize(n);

	double s = 0.0;
	for(int i = 0; i < n; ++i)
	for(int j = i + 1; j < n; ++j)
	for(int k = j + 1; k < n; ++k){
		double u = calc(i, j, k);
		s += u;
	}
	
	printf("%f\n", s);
}

Measured memory_bytes: 1188