HDU 5839 Special Tetrahedron(计算几何)

传送门

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

Author

UESTC

Source

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

题目大意:

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

1:至少有 4 条边相等;

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

解题思路:

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

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

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

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

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

重一下就行了。

My Code:

/**
2016 - 08 - 17 下午
Author: ITAK

Motto:

今日的我要超越昨日的我,明日的我要胜过今日的我,
以创作出更好的代码为目标,不断地超越自己。
**/

#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;
}
时间: 2024-11-13 17:56:37

HDU 5839 Special Tetrahedron(计算几何)的相关文章

hdu 5839 Special Tetrahedron 计算几何 求特殊四面体个数

Special Tetrahedron Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 175    Accepted Submission(s): 64 Problem Description Given n points which are in three-dimensional space(without repetition).

HDU 5839 Special Tetrahedron (2016CCPC网络赛08) (暴力+剪枝)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5839 在一个三维坐标,给你n个点,问你有多少个四面体(4个点,6条边) 且满足至少四边相等 其余两边不相邻. 暴力4重循环,但是在第3重循环的时候需要判断是否是等腰三角形,这便是一个剪枝.在第4重循环的时候判断4点是否共面 (叉乘), 5或者6边相等就+1,4边相等就判断另外两边是否相交就行了. 赛后过的,觉得自己还是太菜了. 1 //#pragma comment(linker, "/STACK:

HDU 5839 Special Tetrahedron

暴力水过,数据水. #pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue>

hdu-5839 Special Tetrahedron(计算几何)

题目链接: Special Tetrahedron Time Limit: 4000/2000 MS (Java/Others)     Memory Limit: 65536/65536 K (Java/Others) Problem Description Given n points which are in three-dimensional space(without repetition). Please find out how many distinct Special Tetr

HDU 3395 Special Fish 最“大”费用最大流

求最大费用可以将边权取负以转化成求最小费用.然而此时依然不对,因为会优先寻找最大流,但是答案并不一定出现在满流的时候.所以要加一些边(下图中的红边)使其在答案出现时满流.设所有边的流量为1,花费如下图所示.显然最大花费是1001,而没有红边的情况下会得到3. #include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio>

HDU 4569 Special equations(数学推论)

题目 //想不出来,看了解题报告 /* 题意:给你一个最高幂为4的一元多项式,让你求出一个x使其结果模p*p为0. 题解:f(x)%(p*p)=0那么一定有f(x)%p=0,f(x)%p=0那么一定有f(x+p)%p=0. 所以我们可以开始从0到p枚举x,当f(x)%p=0,然后再从x到p*p枚举,不过每次都是+p,找到了输出即可,没有的话No solution! */ #include<stdio.h> int main() { int t,n; __int64 a[5],p; scanf(

【HDU 5839】Special Tetrahedron(计算几何)

空间的200个点,求出至少四边相等,且其余两边必须不相邻的四面体的个数. 用map记录距离点i为d的点有几个,这样来优化暴力的四重循环. 别人的做法是枚举两点的中垂面上的点,再把到中点距离相等的点找出来,n^3的样子. 还要注意四个点共面的情况. 共面判断就是用叉乘计算出ijk三点所在面的法向量,然后判断il向量是否和法向量垂直,是则共面. #include <cstdio> #include <cstring> #include <algorithm> #includ

HDU 4063 Aircraft(计算几何)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4063 Description You are playing a flying game. In the game, player controls an aircraft in a 2D-space. The mission is to drive the craft from starting point to terminal point. The craft needs wireless s

HDU 4569 Special equations(取模)

Special equations Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 4569 Description Let f(x) = a nx n +...+ a 1x +a 0, in which a i (0 <= i <= n) are all known integers. We call f(x) 0 (mod