记录编号 |
300463 |
评测结果 |
AAAAAAAAAAA |
题目名称 |
[HNOI 2004] 金属包裹 |
最终得分 |
100 |
用户昵称 |
_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);
}