HDU 5839 Special Tetrahedron(计算几何)——2016中国大学生程序设计竞赛 - 网络选拔赛

来源:互联网 发布:图知天下 编辑:程序博客网 时间:2024/05/21 15:28

传送门

Special Tetrahedron

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 616    Accepted Submission(s): 258


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
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
 

Author
UESTC
 

Source
2016中国大学生程序设计竞赛 - 网络选拔赛

题目大意:

给了 n 个点的三维坐标,判断是不是能够构成一个特殊的四面体,特殊的四面体满足 2 个条件:

1:至少有 4 条边相等;

2:假设有四条边相等的话,另外两条边不想等的必须是对边。

解题思路:

首先我们将每两个点的距离算出来作为线段,将这些线段保留下来,然后两重循环枚举两条相等的

线段,然后再比较这两条直线的端点所到另一条直线的端点的距离是否和直线距离相等,每次枚举

的时候都得判断对边是不是想等,类似下图中,每次枚举红色的线,然后判断黄色或者黑色的,首

先那两条红色的线的四个点判断一下这四个点是不是在同一个平面上,然后再判断是不是特殊的四

面体,因为每次枚举对边,所以能够保证四条边相等,不想等的是对边。然后去重,用一个集合去

重一下就行了。

样图

My Code

/**2016 - 08 - 17 下午Author: ITAKMotto:今日的我要超越昨日的我,明日的我要胜过今日的我,以创作出更好的代码为目标,不断地超越自己。**/#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <vector>#include <queue>#include <algorithm>#include <set>using namespace std;typedef long long LL;typedef unsigned long long ULL;const int INF = 1e9+5;const int MAXN = 2e2+5;const int MOD = 1e9+7;const double eps = 1e-7;const double PI = acos(-1);using namespace std;LL Scan_LL()///输入外挂{    LL res=0,ch,flag=0;    if((ch=getchar())=='-')        flag=1;    else if(ch>='0'&&ch<='9')        res=ch-'0';    while((ch=getchar())>='0'&&ch<='9')        res=res*10+ch-'0';    return flag?-res:res;}int Scan_int()///输入外挂{    int res=0,ch,flag=0;    if((ch=getchar())=='-')        flag=1;    else if(ch>='0'&&ch<='9')        res=ch-'0';    while((ch=getchar())>='0'&&ch<='9')        res=res*10+ch-'0';    return flag?-res:res;}void Out(LL a)///输出外挂{    if(a>9)        Out(a/10);    putchar(a%10+'0');}struct Point{    LL x, y, z;} a[MAXN];inline LL Get_Dis(Point a, Point 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);}bool Judge(Point a, Point b, Point c, Point d)///判断共面;{    LL x1 = b.x-a.x, y1 = b.y-a.y, z1 = b.z-a.z;    LL x2 = c.x-a.x, y2 = c.y-a.y, z2 = c.z-a.z;    LL x3 = d.x-a.x, y3 = d.y-a.y, z3 = d.z-a.z;    LL tmp1 = x1*y2*z3+y1*z2*x3+z1*x2*y3;    LL tmp2 = z1*x3*y2+x2*y1*z3+x1*z2*y3;    if(tmp1 == tmp2)        return 1;    return 0;}struct Line{    LL st, end, len;} line[MAXN*MAXN];inline bool cmp(Line a, Line b){    return a.len < b.len;}struct Check///去重{    int  ind[4];    bool operator < (const Check &x)const    {        if(ind[0] == x.ind[0])        {            if(ind[1] == x.ind[1])            {                if(ind[2] == x.ind[2])                    return ind[3] < x.ind[3];                return ind[2] < x.ind[2];            }            return ind[1] < x.ind[1];        }        return ind[0] < x.ind[0];    }};set <Check> s;int main(){    int T, n;    T = Scan_int();    for(int cas=1; cas<=T; cas++)    {        s.clear();        n = Scan_int();        for(int i=0; i<n; i++)        {            a[i].x = Scan_LL();            a[i].y = Scan_LL();            a[i].z = Scan_LL();        }        int cnt = 0;        for(int i=0; i<n; i++)        {            for(int j=i+1; j<n; j++)            {                line[cnt].len = Get_Dis(a[i], a[j]);                line[cnt].st = i;                line[cnt++].end = j;            }        }        sort(line, line+cnt, cmp);        for(int i=0; i<cnt; i++)        {            Line p1 = line[i];            for(int j=i+1; ; j++)            {                Line p2 = line[j];                if(p1.len != p2.len)                    break;                ///cout<<p1.st<<" "<<p1.end<<" "<<p2.st<<" "<<p2.end<<endl;                if(Judge(a[p1.st], a[p1.end], a[p2.st], a[p2.end]))                    continue;                if(p1.st!=p2.end && p1.end!=p2.st)                {                    LL len1 = Get_Dis(a[p1.st], a[p2.st]);                    LL len2 = Get_Dis(a[p1.st], a[p2.end]);                    LL len3 = Get_Dis(a[p1.end], a[p2.end]);                    LL len4 = Get_Dis(a[p1.end], a[p2.st]);                    if( (len1==len3&&len1==p1.len) || (len2==len4&&len2==p2.len))                    {                        Check tp;                        tp.ind[0] = p1.st;                        tp.ind[1] = p1.end;                        tp.ind[2] = p2.st;                        tp.ind[3] = p2.end;                        sort(tp.ind, tp.ind+4);                        s.insert(tp);                    }                }            }        }        LL ret = s.size();        printf("Case #%d: %I64d\n",cas,ret);    }    return 0;}
0 0
原创粉丝点击