HDU 5839 Special Tetrahedron(几何+暴力)

来源:互联网 发布:非洲人眼中的中国知乎 编辑:程序博客网 时间:2024/06/06 15:39

传送门:点击打开链接

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.
 

Input
Intput contains multiple test cases. 

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

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

The next n lines contains three integers xi,yi,zi(2000xi,yi,zi2000), 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
240 0 00 1 11 0 11 1 090 0 00 0 21 1 1-1 -1 11 -1 1-1 1 11 1 01 0 10 1 1
 

Sample Output
Case #1: 1Case #2: 6
 

题意是在三维空间内有n个点,问这些点能构成多少个特殊四面体。特殊四面体的定义是有4条以上的边相等,若有四条边相等,则需要不相等的两条边不相邻。


纯暴力,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;}