记录编号 300463 评测结果 AAAAAAAAAAA
题目名称 [HNOI 2004] 金属包裹 最终得分 100
用户昵称 Gravatar_Itachi 是否通过 通过
代码语言 C++ 运行时间 0.001 s
提交时间 2016-08-28 16:00:00 内存使用 0.03 MiB
显示代码纯文本
/*
	duang_duang_duang !!
	天空一声巨响,计算几何模板闪亮登场!! 
*/
#include<cstdio>
#include<algorithm>
#include<cmath>
#define EPS 1e-10
double _abs(double x){return x<0?-x:x;}
int _compf(double x){
	if(_abs(x)<EPS)return 0;
	return x<0?-1:1;
}
/*_________________4.1二维几何基础____________________*/
//Begin 
#define _point _vector
struct _vector{
	double x,y;
	_point(double a=0,double b=0){x=a,y=b;}
	bool operator <  (const _point &a)const{
		return x==a.x?y<a.y:x<a.x;
	}
	bool operator >  (const _point &a)const{
		return x==a.x?y>a.y:x>a.x;
	}
	bool operator <= (const _point &a)const{
		return x==a.x?y<=a.y:x<a.x;
	}
	bool operator >= (const _point &a)const{
		return x==a.x?y>=a.y:x>a.x;
	}
	bool operator == (const _point &a)const{
		return _compf(x-a.x)==0&&_compf(y-a.y)==0;
	}
	_vector _0(){return _vector(0.0,0.0);}
	_vector operator + (const _point &a)const{
		return _vector(x+a.x,y+a.y);
	}
	_vector operator - (const _point &a)const{
		return _vector(x-a.x,y-a.y);
	}
	_vector operator * (const double &a)const{
		return _vector(x*a,y*a);
	}
	_vector operator / (const double &a)const{
		return _vector(x/a,y/a);
	}

}; 
double _Dot(_vector a,_vector b){
	return a.x*b.x+a.y*b.y;
}//点积 
double _length(_vector a){
	return sqrt(_Dot(a,a));
}//向量的长度 
double _angle(_vector a){
	return atan2(a.y,a.x);
}//向量的极角 
double _Angle(_vector a,_vector b){
	return acos(_Dot(a,b)/_length(a)/_length(b));
}//向量的夹角
double _cross(_vector a,_vector b){
	return a.x*b.y-a.y*b.x;
}//向量的叉积 
double _Sabc(_point a,_point b,_point c){
	return _cross(a-b,a-c)*0.5;
}//三角形的面积 
_vector _turn(_vector a,double rad){
	double _sin=sin(rad),_cos=cos(rad);
	return _vector(a.x*_cos-a.y*_sin,a.x*_sin+a.y*_cos);
}//旋转 
_vector _normal(_vector a){
	int len=_length(a);
	return _vector(-a.y/len,a.x/len);
}//单位法向量
_point _lin_con(_point a,_vector v,_point b,_vector w){
	_vector u=a-b;
	double t=_cross(w,u)/_cross(v,w);
	return a+v*t;
}//两直线的交点 
double _dis_poi(_point a,_point b){
	return _length(a-b);
}//点到点距离 
double _dis_line(_point p,_point a,_point b){
	_vector v1=p-a,v2=b-a;
	return _abs(_cross(v1,v2))/_length(v2);
}//点到直线距离 
double _dis_seg(_point p,_point a,_point b){
	if(a==b)return _length(p-a);
	_vector va=p-a,vb=p-b,v=a-b;
	if(_compf(_Dot(va,v))>0)return _length(va);
	if(_compf(_Dot(vb,v))<0)return _length(vb);
	return _dis_line(p,a,b);
}//点到线段距离 
_point _pro_line(_point p,_point a,_point b){
	_vector v=a-b;
	return a+v*_Dot(v,p-a)/_Dot(v,v);
}//点到直线的投影
bool _lint_on(_point p,_point a,_point b){
	return _compf(_cross(a-p,b-p))==0;
}//点是否在直线上 
bool _seg_on(_point p,_point a,_point b){
	return _compf(_cross(a-p,b-p))==0&&_compf(_Dot(a-p,b-p))<0;
}//点是否在线段上 
bool _seg_con_on(_point a,_point b,_point c,_point d){
	return _seg_on(a,c,d)||_seg_on(b,c,d)
	||_seg_on(c,a,b)||_seg_on(d,a,b);
}//线段的交点是否在端点 
bool _seg_con(_point a,_point b,_point c,_point d){
	if(_seg_con_on(a,b,c,d))return true;
	double f1=_cross(b-a,c-a),f2=_cross(b-a,d-a),
	       f3=_cross(d-c,a-c),f4=_cross(d-c,b-c);
	return _compf(f1)*_compf(f2)<0&&_compf(f3)*_compf(f4)<0;
}//判断两条线段是否相交,通过判断是否满足
//一条直线的两端点在另一条直线的两侧 
bool _comparea(_point a,_point b){
	return a.y/a.x<b.y/b.x;
}//极角比较 
void _areasort(_point* p,int n){
	std::sort(p,p+n,_comparea);
}//极角排序 
double _Sarea(_point* p,int n){
	double res=0;
	for(int i=1;i<n-1;i++)
		res+=_cross(p[i]-p[0],p[i+1]-p[0]);
	return res*0.5;
}//多边形的面积 (已排好序) 
double _area(_point*p,int n){
	_areasort(p,n);
	return _Sarea(p,n);
}//多边形的面积(未排好序)
//End
/*_________________4.1二维几何基础____________________*/
void _4_1(){
	while(true)while(true)while(true)while(true)_4_1();
}
/*_________________4.2与圆和球有关的计算______________*/
//Begin 
struct _circle{
	_point c;double r;
	_circle(_point a,double R){c=a,r=R;}
	_point _point_on_circle(double rad){
		return _point(c.x+cos(rad)*r,c.y+sin(rad)*r);
	}//求圆上一点 
};
//To be continue...
//End
/*_________________4.2与圆和球有关的计算______________*/
void _4_2(){
	while(true)while(true)while(true)while(true)_4_2();
}
/*_________________4.3二维几何常用算法________________*/
//Begin 
void _oulaingli(){
	if(false){
		/*
		欧拉定理:
			设平面内顶点数,边数,面数分别为V,E,F
			则有 V+F-E=2
			即 F=E-V+2 
		*/
	} 
}//这是一个定理 
bool _on_abc(_point p,_point a,_point b,_point c){
	if(_seg_on(p,a,b)||_seg_on(p,a,c)||_seg_on(p,b,c))return true;
	return false;
}//判断点是否在三角形边上 
bool _bein_abc(_point p,_point a,_point b,_point c,bool ff=0){
	if(_on_abc(p,a,b,c))return !ff;
	double ss=_abs(_cross(p-a,p-b))+_abs(_cross(p-a,p-c))+
		_abs(_cross(p-b,p-c)),s=_abs(_cross(a-b,a-c));
	return _compf(ss-s)==0;
}//判断点是否在三角形内(传点) 
bool _bein_abc(_point a,_point* p,bool ff=0){
	double s=_abs(_cross(p[0]-p[1],p[0]-p[2])),ss=0;
	for(int i=0;i<3;i++){
		if(_seg_on(a,p[i],p[(i+1)%3]))return !ff;
		ss+=_abs(_cross(a-p[i],a-p[(i+1)%3]));
	}	
	return _compf(ss-s)==0;
}//判断点是否在三角形内(传数组)
bool _point_in(_point a,_point* p,int n,bool ff=0){
	if(ff)_areasort(p,n);
	int res=0,i,c1,c2;double k;
	for(i=0;i<n;i++){
		if(_seg_on(a,p[i],p[(i+1)%n]))return false;//看情况更改 
		k=_cross(p[(i+1)%n]-p[i],a-p[i]);
		c1=_compf(a.y-p[i].y),c2=_compf(a.y-p[(i+1)%n].y);
		if(k>0&&c1>=0&&c2<0)res++;//穿入 
		if(k<0&&c1<0&&c2>=0)res--;//穿出 
	}
	if(res)return true;
	return false;
}//判断点是否在多边形内 
int _cover(_point* p,int n,_point* ans,bool ff=0){
	if(ff)std::sort(p,p+n);int res=0,k;
	for(int i=0;i<n;i++){
		while(res>1&&
		_cross(ans[res-1]-ans[res-2],p[i]-ans[res-2])<=0)res--;
		ans[res++]=p[i];
	}
	k=res;
	for(int i=n-2;i>-1;i--){
		while(res>k&&
		_cross(ans[res-1]-ans[res-2],p[i]-ans[res-2])<=0)res--;
		ans[res++]=p[i];
	}
	if(n>1)res--;
	return res;
}//求凸包边上的顶点数并存在ans里 
//End
/*_________________4.3二维几何常用算法________________*/
void _4_3(){
	while(true)while(true)while(true)while(true)_4_3();
}
/*_________________4.4三维几何基础____________________*/
//Begin 
#include<vector>
#include<cstdlib>
#include<ctime>
using namespace std;
const int maxn=105;
struct _3{
	double x,y,z;
	_3(double a=0,double b=0,double c=0){x=a,y=b,z=c;}
	_3 operator + (const _3 &a)const{
		return _3(x+a.x,y+a.y,z+a.z);
	}
	_3 operator - (const _3 &a)const{
		return _3(x-a.x,y-a.y,z-a.z);
	}
	_3 operator * (const double &a)const{
		return _3(x*a,y*a,z*a);
	}
	_3 operator / (const double &a)const{
		return _3(x/a,y/a,z/a);
	}
}p[maxn],y[maxn];
double _D(_3 a,_3 b){
	return a.x*b.x+a.y*b.y+a.z*b.z;
}
double _L(_3 a){
	return sqrt(_D(a,a));
}
double _A(_3 a,_3 b){
	return acos(_D(a,b)/_L(a)/_L(b));
}
_3 _C(_3 a,_3 b){
	return _3(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x);
}
double _area3(_3 a,_3 b,_3 c){
	return _L(_C(b-a,c-a));
}
struct _face{
	int v[3];
	_face(int a=0,int b=0,int c=0){v[0]=a,v[1]=b,v[2]=c;}
	_3 _N()const{
		return _C(p[v[1]]-p[v[0]],p[v[2]]-p[v[0]]);
	}
	bool cansee(int i)const{
		return _D(p[i]-p[v[0]],_N())>0;
	}
	double Area()const{
		return _area3(y[v[0]],y[v[1]],y[v[2]]);
	}
};
double _rand01(){
	return rand()/(double)RAND_MAX;
}
double _rand(){
	return (_rand01()-0.5)*EPS;
}
_3 _(_3 a){
	return _3(a.x+_rand(),a.y+_rand(),a.z+_rand());
}
bool vis[maxn][maxn];
vector<_face>res;
int _VCH3D(int n){
	res.push_back(_face(0,1,2)),res.push_back(_face(2,1,0));
	int i,j,k,a,b;bool ff;
	for(i=3;i<n;i++){
		vector<_face>next;
		for(j=0;j<res.size();j++){
			_face& f=res[j];
			ff=f.cansee(i);
			if(!ff)next.push_back(f);
			for(k=0;k<3;k++)vis[f.v[k]][f.v[(k+1)%3]]=ff;
		}
		for(j=0;j<res.size();j++)
		for(k=0;k<3;k++){
			a=res[j].v[k],b=res[j].v[(k+1)%3];
			if(vis[a][b]^vis[b][a]&&vis[a][b])
				next.push_back(_face(a,b,i));
		}
		res=next;
	}
	return res.size();
}//最小体积凸包 
double _S_VCH3D(int n){
	double ans=0;int size=_VCH3D(n);
	for(int i=0;i<size;i++)
		ans+=res[i].Area();
	return ans*0.5;
}//最小体积凸包的表面积
double _SCH3D(int a,int b,int c,int n){
	_3 N=_C(p[b]-p[a],p[c]-p[a]);bool f1=false,f2=false;
	for(int i=0;i<n;i++)
	if(i^a&&i^b&&i^c){
		if(_D(p[i]-p[a],N)<0)f1=true;
		else f2=true;
		if(f1&&f2)return 0;
	}
	return _area3(y[a],y[b],y[c]);
}//最小表面积的凸包 
double _S_SCH3D(int n){
	double ans=0;int i,j,k;
	for(i=0;i<n;i++)
	for(j=0;j<i;j++)
	for(k=0;k<j;k++)
		ans+=_SCH3D(i,j,k,n);
	return ans*0.5;
}//最小表面积凸包的表面积 
//To be continue...
//End
/*_________________4.4三维几何基础____________________*/
void _4_4(){
	while(true)while(true)while(true)while(true)_4_4();
}
bool _Rabit(),_RABIT=_Rabit();int main(){;}
bool _Rabit(){
	freopen("enwrap.in","r",stdin);freopen("enwrap.out","w",stdout);
	int i,n;scanf("%d",&n);srand(time(NULL));
	for(i=0;i<n;i++)
		scanf("%lf%lf%lf",&y[i].x,&y[i].y,&y[i].z),p[i]=_(y[i]);
	printf("%.6lf\n",_S_SCH3D(n));
	fclose(stdin);fclose(stdout);
}