• 【HDU 5839】Special Tetrahedron(计算几何)


    空间的200个点,求出至少四边相等,且其余两边必须不相邻的四面体的个数。

    用map记录距离点i为d的点有几个,这样来优化暴力的四重循环。

    别人的做法是枚举两点的中垂面上的点,再把到中点距离相等的点找出来,n^3的样子。

    还要注意四个点共面的情况。

    共面判断就是用叉乘计算出ijk三点所在面的法向量,然后判断il向量是否和法向量垂直,是则共面。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <map>
    #define eps (1e-6)
    #define N 205
    #define dd double
    #define sqr(x) ((x)*(x))
    using namespace std;
    map<double,int>mm[N];
    int ok[N];
    struct node{
        int x,y,z;
    }a[N];
    dd Dis[N][N];
    dd dis(int i,int j)
    {
        if(Dis[i][j])return Dis[i][j];
        return Dis[i][j]=sqrt(sqr(a[i].x-a[j].x)+sqr(a[i].y-a[j].y)+sqr(a[i].z-a[j].z));
    }
    node xmul(node i,node j,node k){
            int z=(i.x-j.x)*(k.y-j.y)-(i.y-j.y)*(k.x-j.x);
            int y=(i.z-j.z)*(k.x-j.x)-(i.x-j.x)*(k.z-j.z);
            int x=(i.y-j.y)*(k.z-j.z)-(i.z-j.z)*(k.y-j.y);
            return (node){x,y,z};
    }
    node xmul(int i,int j,int k){
        return xmul(a[i],a[j],a[k]);
    }
    int sgn(dd a,dd b){
        return fabs(a-b)>-eps&&fabs(a-b)<eps;
    }
    int te(int i,int j,int k,int l){//共面
        node il=(node){a[i].x-a[l].x,a[i].y-a[l].y,a[i].z-a[l].z};
        node s=xmul(i,j,k);
        return s.x*il.x+s.y*il.y+s.z*il.z;
    }
    int main() {
        int t,n;
        scanf("%d",&t);
        for(int cas=1;cas<=t;cas++){
            scanf("%d",&n);
            for(int i=1;i<=n;i++)
                scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
            int ans=0,same=0;
            memset(ok,0,sizeof ok);
            memset(Dis,0,sizeof Dis);
            for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)mm[i].clear();
            for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++){
                mm[i][dis(i,j)]++;
                if(mm[i][dis(i,j)]>1){ok[i]=1;break;}
            }
            for(int i=1;i<=n;i++)if(ok[i])
            for(int j=i+1;j<=n;j++)if(ok[j])
            for(int k=i+1;k<=n;k++)if(ok[k]){
                    dd ij=dis(i,j),ik=dis(i,k),jk=dis(j,k);
                    if(sgn(jk,ik))
                        for(int l=k+1;l<=n;l++)if(l!=j){
                            dd jl=dis(j,l),lk=dis(l,k),il=dis(i,l);
                            if(te(i,j,k,l)){
                                if(sgn(jk,jl)&&sgn(jl,il)&&sgn(il,jl))
                                {
                                    ans++;
                                    if(sgn(ij,lk)&&sgn(ij,ik))same++;
                                }
                            }                    
                        }
            }
            printf("Case #%d: %d
    ",cas,ans-same/3*2);//全部边相同的会计算3次
        }
    }

    赛后做出来的,为什么当时暴力都写不出来呢,因为在防止多算的时候给漏算了。枚举出错。

  • 相关阅读:
    对象序列化流使用
    字符输入流结合字符打印流实现复制文件
    python 安装一些 直接使用pip无法安装的包 的方法
    linux记不住
    SIP
    uniapp不同型号手机适配
    uniapp app头部渐变
    vue安卓苹果下载链接合并
    Typescript
    Nodejs
  • 原文地址:https://www.cnblogs.com/flipped/p/5771398.html
Copyright © 2020-2023  润新知