HDU 3662 3D Convex Hull(三维凸包面的个数)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3662

题意:求三维凸包面的个数。

思路:模板。



struct Point
{
    double x,y,z;

    Point() {}
    Point(double _x,double _y,double _z)
	{
		x=_x;
		y=_y;
		z=_z;
	}

	void Get()
	{
	    RD(x,y,z);
	}
    Point operator-(const Point p1)
	{
		return Point(x-p1.x,y-p1.y,z-p1.z);
	}

    Point operator*(Point p)
	{
		return Point(y*p.z-z*p.y,z*p.x-x*p.z,x*p.y-y*p.x);
	}
    double operator^(Point p)
	{
		return x*p.x+y*p.y+z*p.z;
	}

	double len()
	{
	    return sqrt(sqr(x)+sqr(y)+sqr(z));
	}
};

struct _3DCH
{
    struct face
    {
        int a,b,c,ok;

        face(){}
        face(int _a,int _b,int _c,int _ok)
        {
            a=_a;
            b=_b;
            c=_c;
            ok=_ok;
        }
    }F[N<<2];
    int n,cnt,b[N][N];
    Point p[N];

    int DB(double x)
    {
        if(x>1e-10) return 1;
        if(x<-1e-10) return -1;
        return 0;
    }

    double vlen(Point a)
    {
        return a.len();
    }

    double getArea(Point a,Point b,Point c)
    {
        return vlen((b-a)*(c-a));
    }

    double getVolume(Point a,Point b,Point c,Point d)
    {
        return (b-a)*(c-a)^(d-a);
    }

    //t在f的正面返回1,反面返回-1,在f上返回0
    int getDir(Point t,face f)
    {
        double x=(p[f.b]-p[f.a])*(p[f.c]-p[f.a])^(t-p[f.a]);
        return DB(x);
    }

    void deal(int i,int x,int y)
    {
        int f=b[x][y];
        face temp;
        if(!F[f].ok) return;
        if(getDir(p[i],F[f])>0) DFS(i,f);
        else
        {
            temp=face(y,x,i,1);
            b[y][x]=b[x][i]=b[i][y]=cnt;
            F[cnt++]=temp;
        }
    }

    void DFS(int i,int j)
    {
        F[j].ok=0;
        deal(i,F[j].b,F[j].a);
        deal(i,F[j].c,F[j].b);
        deal(i,F[j].a,F[j].c);
    }

    void construct()
    {
        if(n<4) return;
        int i,j,k=0;
        FOR1(i,n-1) if(DB(vlen(p[0]-p[i])))
        {
            swap(p[1],p[i]);
            k=1;
            break;
        }
        if(!k) return;
        k=0;
        FOR(i,2,n-1) if(DB(getArea(p[0],p[1],p[i])))
        {
            swap(p[2],p[i]);
            k=1;
            break;
        }
        if(!k) return;;
        k=0;
        FOR(i,3,n-1) if(DB(getVolume(p[0],p[1],p[2],p[i])))
        {
            swap(p[3],p[i]);
            k=1;
            break;
        }
        if(!k) return;

        cnt=0;
        face temp;
        FOR0(i,4)
        {
            temp=face((i+1)%4,(i+2)%4,(i+3)%4,1);
            if(getDir(p[i],temp)>0) swap(temp.b,temp.c);
            b[temp.a][temp.b]=b[temp.b][temp.c]=b[temp.c][temp.a]=cnt;
            F[cnt++]=temp;
        }

        FOR(i,4,n-1) FOR0(j,cnt) if(F[j].ok&&getDir(p[i],F[j])>0)
        {
            DFS(i,j);
            break;
        }
        j=0;
        FOR0(i,cnt) if(F[i].ok) F[j++]=F[i];
        cnt=j;
    }

    double getSumArea()
    {
        double ans=0;
        int i;
        FOR0(i,cnt) ans+=getArea(p[F[i].a],p[F[i].b],p[F[i].c]);
        return ans/2;
    }

    int isSame(face a,face b)
    {
        Point x1=p[a.a],y1=p[a.b],z1=p[a.c];
        Point x2=p[b.a],y2=p[b.b],z2=p[b.c];
        if(DB(getVolume(x1,y1,z1,x2))) return 0;
        if(DB(getVolume(x1,y1,z1,y2))) return 0;
        if(DB(getVolume(x1,y1,z1,z2))) return 0;
        return 1;
    }

    int getFactNum()
    {
        int ans=0,i,j;
        FOR0(i,cnt)
        {
            FOR(j,i+1,cnt-1) if(isSame(F[i],F[j]))
            {
                break;
            }
            ans+=j>=cnt;
        }
        return ans;
    }
};

_3DCH a;

int main()
{
    while(scanf("%d",&a.n)!=-1)
    {
        int i;
        FOR0(i,a.n) a.p[i].Get();
        a.construct();
        int s=a.getFactNum();
        printf("%d\n",s);
    }
    return 0;
}

  

 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值