HDU 5839 Special Tetrahedron 计算几何

Special Tetrahedron

题目连接:

http://acm.hdu.edu.cn/showproblem.php?pid=5839

Description

Given n points which are in three-dimensional space(without repetition).

Please find out how many distinct Special Tetrahedron among them. A tetrahedron is called Special Tetrahedron if it has two following characters.

  1. At least four edges have the same length.

  2. If it has exactly four edges of the same length, the other two edges are not adjacent.

Input

Intput contains multiple test cases.

The first line is an integer T,1≤T≤20, the number of test cases.

Each case begins with an integer n(n≤200), indicating the number of the points.

The next n lines contains three integers xi,yi,zi, (−2000≤xi,yi,zi≤2000), representing the coordinates of the ith point.

Output

For each test case,output a line which contains"Case #x: y",x represents the xth test(starting from one),y is the number of Special Tetrahedron.

Sample Input

2
4
0 0 0
0 1 1
1 0 1
1 1 0
9
0 0 0
0 0 2
1 1 1
-1 -1 1
1 -1 1
-1 1 1
1 1 0
1 0 1
0 1 1

Sample Output

Case #1: 1
Case #2: 6

Hint

题意

给你三维一些点,问你有多少个四边形满足以下条件

1.至少四个边相同

2.如果四个边相同,那么不相同的两个边不在一起。

题解:

n^4暴力,但实际上复杂度达不到n^4【和出题人是否懒惰有关,233

暴力枚举两个点,然后再枚举离这两点距离相同的点。

再枚举四个点,找到这个四边形四边相同,但是不共面的四个点。

再判断这个是不是正四边形,如果是正四边形的话,你会重复计算6次

否则重复计算两次。

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 205;
struct point
{
    int x,y,z;
    point(){}
    point(int x_,int y_,int z_):x(x_),y(y_),z(z_) {}
}p[210];
long long sq(long long a){
    return a*a;
}
long long dis(point a,point b){
    return sq(a.x-b.x)+sq(a.y-b.y)+sq(a.z-b.z);
}
bool check(point a,point b,point c,point d)
{
    point s1,s2,s3;
    s1.x=b.x-a.x;s1.y=b.y-a.y;s1.z=b.z-a.z;
    s2.x=c.x-a.x;s2.y=c.y-a.y;s2.z=c.z-a.z;
    s3.x=d.x-a.x;s3.y=d.y-a.y;s3.z=d.z-a.z;
    long long ans=s1.x*s2.y*s3.z+s1.y*s2.z*s3.x+s1.z*s2.x*s3.y-s1.z*s2.y*s3.x-s1.x*s2.z*s3.y-s1.y*s2.x*s3.z;
    if(ans==0)return true;
    return false;
}
int Q[300],cas;
void solve(){
    int n;scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z);
    }
    long long ans1=0,ans2=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
        {
            int cnt=0;
            for(int k=1;k<=n;k++)
            {
                if(k==i||k==j)continue;
                if(dis(p[i],p[k])==dis(p[j],p[k]))
                    Q[cnt++]=k;
            }
            if(cnt<=1)continue;
            for(int i1=0;i1<cnt;i1++)
            {
                for(int j1=i1+1;j1<cnt;j1++)
                {
                    int id1=Q[i1],id2=Q[j1];
                    if(dis(p[id1],p[i])!=dis(p[id2],p[i]))continue;
                    if(check(p[i],p[j],p[id1],p[id2]))continue;
                    if(dis(p[i],p[j])==dis(p[id1],p[i])&&dis(p[i],p[j])==dis(p[id1],p[id2]))ans2++;
                    else ans1++;
                }
            }
        }
    }
    printf("Case #%d: %d\n",++cas,ans1/2+ans2/6);
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--)solve();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值