传送门:点击打开链接
Special Tetrahedron
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 843 Accepted Submission(s): 348
Problem 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.
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.
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
纯暴力,n层循环。枚举两个点,就相当于一条边,判断第三个点到这两个点的距离,若是距离相等,则记录这个点的编号,若这样的点存在两个及以上,就从其中取出两个点,首先判断四个点是否共面,然后判断这四个点有几个点相等,若是六条边相等需要单独记录,另外需要记录相等边大于等于4且小于6的情况。注意枚举的时候,四个点不能相同。最后得到两种结果,6条边都相等的,需要除以6,因为6条边都记录了一次,另一种情况需要除以2,因为记录了两次。最后输出结果,没想到暴力居然过了。
代码实现:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<cstdio>
#define ll long long
#define mset(a,x) memset(a,x,sizeof(a))
using namespace std;
const double PI=acos(-1);
const int inf=0x3f3f3f3f;
const double esp=1e-12;
const int maxn=1005;
const int mod=1e9+7;
int dir[4][2]={0,1,1,0,0,-1,-1,0};
struct point{
ll x,y,z;
}p[205];
ll lenth[maxn];
ll judge(point a,point b,point c,point d) //判断是否共面
{
point u,v,w;
u.x=b.x-a.x;u.y=b.y-a.y;u.z=b.z-a.z;
v.x=c.x-a.x;v.y=c.y-a.y;v.z=c.z-a.z;
w.x=d.x-a.x;w.y=d.y-a.y;w.z=d.z-a.z;
long long ans=u.x*v.y*w.z+u.y*v.z*w.x+u.z*v.x*w.y-u.z*v.y*w.x-u.x*v.z*w.y-u.y*v.x*w.z;
if(ans==0)
return 1;
return 0;
}
ll dis(point a,point b) //求两点间距离
{
return (b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y)+(b.z-a.z)*(b.z-a.z);
}
int main()
{
int n,i,j,k,l,t,ans1,ans2,ans,flag=1,r;
cin>>t;
while(t--)
{
mset(p,0);
mset(lenth,0);
cin>>n;
for(i=0;i<n;i++)
cin>>p[i].x>>p[i].y>>p[i].z;
ans1=ans2=0;
for(i=0;i<n;i++) //枚举第一个点
{
for(j=i+1;j<n;j++) //枚举第二个点
{
int count=0; //下标为0
for(k=0;k<n;k++) //枚举第三个点
{
if(k==i||k==j) //判重
continue;
if(dis(p[i],p[k])==dis(p[j],p[k])) //这点到两点的距离相等
lenth[count++]=k; //记录
}
if(count<=1)
continue;
else
{
for(l=0;l<count;l++) //枚举符合题意的点
{
for(r=l+1;r<count;r++)
{
int temp1=lenth[l]; //记录当前枚举的点
int temp2=lenth[r];
if(dis(p[temp1],p[i])!=dis(p[temp2],p[i])) //两边距离不相等
continue;
if(judge(p[i],p[j],p[temp1],p[temp2])) //共面
{
continue;
}
if(dis(p[temp1],p[temp2])==dis(p[i],p[j])&&(dis(p[i],p[j])==dis(p[temp1],p[i]))&&(dis(p[i],p[j])==dis(p[i],p[temp2])))
ans1++;
else //大于等于四条边情况
ans2++;
}
}
}
}
}
ans=ans1/6+ans2/2;
cout<<"Case #"<<flag++<<": ";
cout<<ans<<endl;
}
return 0;
}