您的位置:首页 > 理论基础 > 计算机网络

2016中国大学生程序设计竞赛 - 网络选拔赛 hdu 5839 Special Tetrahedron

2016-08-15 11:13 495 查看
题目大意:空间中有n个点,选出四个点构成一个四面体,四面体满足

1、至少四条边相等

2、如果四条边相等,不相等的两条边不相邻

解题思路:

1)先枚举两个点P1,P2。构造一个以这两点为法向量,且经过这条线段中点m1的平面。(空间平面方程:平面法向量为 n=(A,B,C),平面方程就为Ax+By+Cz=d)。

2)判断在此平面中的点,记录下来。在这些点中枚举两个点P3,P4。满足,这两个点的中点与P1,P2中点的连线垂直P3,P4的连线。这样可以保证至少有四条边相等且不相邻。(两个全等的等腰三角形构成的四面体)。

3)去重。画一下可以发现,六条边相同这个四面体被重复统计了六次。非六条边相等,被重复统计了两次。

注意:在判断六条边是否相等,除了判断P1,P2长度和P3,P4长度是否相等外,还要判断是否和另外相等的四条边是否相等。

比较两个中点坐标,看是否能构成四面体。

精度也要开到位。

此题的测试数据没有重复点,所以也不需要进行去重。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#define eps 1e-9
using namespace std;
typedef long long ll;
ll eq,neq;/// 统计六条边相等和非六条边相同的情况
ll ans;
int n;
struct node
{
double x,y,z;
}p[500];
bool cmp(node a,node b)
{
if(fabs(a.x-b.x)<=eps)
{
if(fabs(a.y-b.y)<=eps)
return a.z<b.z;
return a.y<b.y;
}
return a.x<b.x;
}
double dis(node a,node b)
{
return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z);
}
void work(node a,node b){
int getin[300];
int cnt=0;
double dis1=dis(a,b);/// P1,P2两点之间的距离
double dis2,dis3;
node mid;
mid.x=(a.x+b.x)/2;
mid.y=(a.y+b.y)/2,mid.z=(a.z+b.z)/2;/// P1,P2的中点坐标
double k1,k2,k3,d;
k1=a.x-b.x,k2=a.y-b.y,k3=a.z-b.z;   /// 平面方程
d=k1*mid.x+k2*mid.y+k3*mid.z;
for(int i=0;i<n;i++)
{
if(fabs(k1*p[i].x+k2*p[i].y+k3*p[i].z-d)<=eps)///找出在此平面中的点
getin[cnt++]=i;
}
if(cnt<1)
return ;
node mid2;
double m1,m2,m3;
double l1,l2,l3;
for(int i=0;i<cnt;i++)
{
dis3=dis(a,p[getin[i]]);
for(int j=i+1;j<cnt;j++)
{
mid2.x=(p[getin[i]].x+p[getin[j]].x)/2;
mid2.y=(p[getin[i]].y+p[getin[j]].y)/2;
mid2.z=(p[getin[i]].z+p[getin[j]].z)/2;     ///P3,P4的中点坐标
if((fabs(mid.x-mid2.x)<=eps)&&(fabs(mid.y-mid2.y)<=eps)&&(fabs(mid.z-mid2.z)<=eps))///中点相同构不成四面体
continue;
m1=mid2.x-mid.x;m2=mid2.y-mid.y;m3=mid2.z-mid.z;
l1=p[getin[i]].x-p[getin[j]].x;
l2=p[getin[i]].y-p[getin[j]].y;
l3=p[getin[i]].z-p[getin[j]].z;
if(fabs(m1*l1+m2*l2+m3*l3)<=eps) /// 判断几条边相同
{
dis2=dis(p[getin[i]],p[getin[j]]);
if(fabs((dis1-dis2))<=eps&&fabs(dis1-dis3)<=eps)
eq++;
else neq++;
}
}
}

}
int main()
{
int cas=0;
int T;
scanf("%d",&T);
while(T--)
{
ans=0;
eq=0,neq=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].z);
}
///=======================================查重,不影响结果,可不加
sort(p,p+n,cmp);
int nn=1;
for(int i=1;i<n;i++)
{
if((fabs(p[i].x-p[i-1].x)<=eps)&&(fabs(p[i].y-p[i-1].y)<=eps)&&(fabs(p[i].z-p[i-1].z)<=eps))
continue;
else
{
p[nn].x=p[i].x;
p[nn].y=p[i].y;
p[nn].z=p[i].z;
nn++;
}
}
n=nn;
///=================================================
if(n<4)
{
printf("Case #%d: 0\n",++cas);
continue;
}
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)///枚举P1,P2
{
work(p[i],p[j]);
}
}
ans=eq/6+neq/2;
printf("Case #%d: %I64d\n",++cas,ans);
}
return 0;
}


a235
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  计算几何 ACM
相关文章推荐