• bzoj 1964: hull 三维凸包 计算几何


    1964: hull 三维凸包

    Time Limit: 1 Sec  Memory Limit: 64 MB
    Submit: 54  Solved: 39
    [Submit][Status][Discuss]

    Description

    三维凸包问题是一个基础的三维计算几何问题,不过这次你只需要做一个简单版的三维凸包问题就行了。

    Input

    输入数据一共有若干行,每行三个整数,表示一个点的坐标。点的个数为五个。

    Output

    输出一个实数,保留两位小数,表示三维凸包的体积。

    Sample Input

    0 0 0
    2 0 0
    0 2 0
    2 2 0
    1 1 1

    Sample Output

    1.33

    HINT

    对于所有数据,坐标范围在[0,100]*[0,100]*[0,100]。

      直接水过,不过网上的三维凸包的标程一个比一个不靠谱,由一组数据拍出来,加上我的程序,三个程序三个答案。整个人都不好了。

      枚举一个面,使得剩下两个点与这条面组成四面体的有向体积符号不同,则两点在面的两侧,计算即可。

      四面体的计算公式是三个向量组成的矩阵行列式的1/6.

      这是居然我的第一个三维算几题。

      另外,这个方法的正确性我还是比较怀疑,因为存在数据是他和网上的三维算几模板矛盾,虽然大部分可以看出是网上的程序的问题,但是居然他与我自己写的版有矛盾,就姑且把它当成骗分暴力吧。(最后有三维凸包程序)

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define MAXN 10
    typedef double real;
    struct point
    {
            real x,y,z;
            point(real x,real y,real z):x(x),y(y),z(z){}
            point(){}
            void read()
            {
                    scanf("%lf %lf %lf",&x,&y,&z);
            }
    }pl[MAXN];;
    real area(point p1,point p2,point p3)
    {
            return (p1.x*p2.y*p3.z + p1.z*p2.x*p3.y + p1.y*p2.z*p3.x
                    -p1.x*p2.z*p3.y - p1.z*p2.y*p3.x - p1.y*p2.x*p3.z)/6;
    }
    point operator -(point p1,point p2)
    {
            return point(p2.x-p1.x,p2.y-p1.y,p2.z-p1.z);
    }
    typedef point line;
    
    bool vis[MAXN];
    int main()
    {
            freopen("input.txt","r",stdin);
            for (int i=0;i<5;i++)
            {
                    pl[i].read();
            }
    //        printf("%.2lf
    ",area(pl[1]-pl[0],pl[2]-pl[0],pl[3]-pl[0]));
            real ans=0;
            real s1,s2,s3;
            for (int a=0;a<5;a++)
            {
                    vis[a]=true;
                    for (int b=0;b<5;b++)
                    {
                            if (vis[b])continue;
                            vis[b]=true;
                            for (int c=0;c<5;c++)
                            {
                                    if (vis[c])continue;
                                    vis[c]=true;
                                    for (int d=0;d<5;d++)
                                    {
                                            if (vis[d])continue;
                                            vis[d]=true;
                                            for (int e=0;e<5;e++)
                                            {
                                                    if (vis[e])continue;
                                                    vis[e]=true;
                                                    s3=abs(s1=area(pl[c]-pl[a],pl[b]-pl[a],pl[d]-pl[a]))+abs(s2=area(pl[c]-pl[a],pl[b]-pl[a],pl[e]-pl[a]));
                                                    if (s1*s2>0)
                                                    {
                                                            vis[e]=false;continue;
                                                    }
                                                    if (s1==0 && s2==0)
                                                    {
                                                            vis[e]=false;continue;
                                                    }
                                                    ans=max(ans,s3);
                                                    vis[e]=false;
                                            }
                                            vis[d]=false;
                                    }
                                    vis[c]=false;
                            }
                            vis[b]=false;
                    }
                    vis[a]=false;
            }
            printf("%.2lf
    ",ans);
    }
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<assert.h>
    #include<vector>
    using namespace std;
    #define MAXN 120
    #define eps 1e-8
    typedef double real;
    inline int sgn(real x)
    {
            if (abs(x)<eps)return 0;
            return x<0?-1:1;
    }
    struct point
    {
            real x,y,z;
            point(real x,real y,real z):x(x),y(y),z(z){}
            point(){}
            int read()
            {
                    return scanf("%lf %lf %lf
    ",&x,&y,&z);
            }
            void noise()
            {
                    x+=(real)(rand()%10000-5000)/10000*eps;
                    y+=(real)(rand()%10000-5000)/10000*eps;
                    z+=(real)(rand()%10000-5000)/10000*eps;
            }
            real len()
            {
                    return sqrt(x*x+y*y+z*z);
            }
    };
    typedef point vect;
    struct line
    {
            point ps;
            real x,y,z;
            line(){}
            line(point p1,point p2)
            {
                    ps=p1;
                    x=p2.x-p1.x;
                    y=p2.y-p1.y;
                    z=p2.z-p1.z;
            }
            line(point ps,real x,real y,real z):ps(ps),x(x),y(y),z(z){}
    };
    vect xmul(line l1,line l2)
    {
            return vect(l1.y*l2.z-l1.z*l2.y,l1.z*l2.x-l1.x*l2.z,l1.x*l2.y-l1.y*l2.x);
    }
    real volume(line l1,line l2,line l3)
    {
            return + l1.x*l2.y*l3.z - l1.x*l2.z*l3.y 
                   - l1.y*l2.x*l3.z + l1.y*l2.z*l3.x
                   + l1.z*l2.x*l3.y - l1.z*l2.y*l3.x;
    }
    //+1 2 3
    //-1 3 2
    //-2 1 3
    //+2 3 1
    //+3 1 2
    //-3 2 1
    struct surface
    {
            point ps;
            real x1,y1,z1;
            real x2,y2,z2;
            surface(){}
            surface(point p1,point p2,point p3)
            {
                    ps=p1;
                    x1=p2.x-p1.x,y1=p2.y-p1.y,z1=p2.z-p1.z;
                    x2=p3.x-p1.x,y2=p3.y-p1.y,z2=p3.z-p1.z;
            }
            real volume(point pt)
            {
                    return ::volume(line(ps,pt),line(ps,x1,y1,z1),line(ps,x2,y2,z2));
            }
            vect nvect()
            {
                    return xmul(line(ps,x1,y1,z1),line(ps,x2,y2,z2));
            }
            void reverse()
            {
                    swap(x1,x2);
                    swap(y1,y2);
                    swap(z1,z2);
            }
    };
    point pl[MAXN];
    struct face
    {
            int pt[3];
            face(int x,int y,int z)
            {
                    pt[0]=x;pt[1]=y;pt[2]=z;
            }
            surface ToSurface()
            {
                    return surface(pl[pt[0]],pl[pt[1]],pl[pt[2]]);
            }
            void print()
            {
                    printf("Face:%d %d %d
    ",pt[0],pt[1],pt[2]);
            }
    };
    vector<face> cc;
    vector<pair<int,int> > chs;
    bool status[MAXN][MAXN];
    int main()
    {
            freopen("input.txt","r",stdin);
            int n=0;
            while (~pl[n++].read());
            n--;
            for (int i=0;i<n;i++)
                    pl[i].noise();
        /*    for (int i=0;i<n;i++)
                    swap(pl[rand()%n],pl[rand()%n]);*/
            cc.push_back(face(0,1,2));
            cc.push_back(face(2,1,0));
            for (int i=0;i<3;i++)
                    status[i][(i+1)%3]=true;
            for (int i=1;i<4;i++)
                    status[i%3][i-1]=true;
            for (int i=3;i<n;i++)
            {
                    //for (int j=0;j<cc.size();j++)cc[j].print();    printf("
    ");
                    chs.clear();
                    for (int j=0;j<cc.size();j++)
                    {
                            if (cc[j].ToSurface().volume(pl[i])<0)
                            {
                                    for (int k=0;k<3;k++)
                                    {
                                            status[cc[j].pt[k]][cc[j].pt[(k+1)%3]]=false;
                                            chs.push_back(make_pair(cc[j].pt[k],cc[j].pt[(k+1)%3]));
                                    }
                                    swap(cc[j],cc[cc.size()-1]);
                                    cc.pop_back();
                                    j--;
                            }
                    }
                    for (int j=0;j<chs.size();j++)
                    {
                            if (!status[chs[j].first][chs[j].second] && status[chs[j].second][chs[j].first])continue;
                            chs[j]=chs[chs.size()-1];
                            j--;
                            chs.pop_back();
                    }
                    for (int j=0;j<chs.size();j++)
                    {
                            cc.push_back(face(i,chs[j].first,chs[j].second));
                            status[i][chs[j].first]=status[chs[j].first][chs[j].second]=status[chs[j].second][i]=true;
                    }
                    for (int j=0;j<n;j++)
                            for (int k=0;k<n;k++)
                                    assert(!(status[j][k]^status[k][j]));
            }
            //for (int j=0;j<cc.size();j++)cc[j].print();    printf("
    ");
            real ans=0;
            for (int i=0;i<cc.size();i++)
            {
                    ans+=cc[i].ToSurface().volume(point(0,0,0))/6;
            }
            printf("%.2lf
    ",abs(ans));
    }
  • 相关阅读:
    注册事件为何无效,没有触发? AUTOPOSTBACK已经设置为TRUE
    不使用web服务实现文本框自动完成扩展
    实现一个搜索功能思路
    QT练习3:QT数字和滚动条关联
    Qt 显示图片 放大 缩小 移动
    QT 的信号与槽机制介绍
    一个有很多QT免费应用例程的网站
    yafeilinux.com的开源项目非常好的东西
    vector的用法
    C语言实现获取LINUX当前时间
  • 原文地址:https://www.cnblogs.com/mhy12345/p/4423697.html
Copyright © 2020-2023  润新知