HDU 5839 Special Tetrahedron (計算幾何)


Special Tetrahedron

題目鏈接:

http://acm.hdu.edu.cn/showproblem.php?pid=5839

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

Source

2016中國大學生程序設計競賽 - 網絡選拔賽
##題意: 在三維空間中給出N個點,找有多少個滿足條件的四面體. 1. 四面體至少有四條邊相等 2. 若恰好四條邊相等,那么剩下的兩邊不相鄰.
##題解: 四面體中每條邊僅有一條邊與它不相鄰, 可以轉化一下題目的條件: 尋找四邊相等的空間四邊形(不能四點共面). 首先枚舉該空間四邊形中的一條對角線,再計算剩余的點跟這條對角線兩端點的距離. 若某點與這對角線兩端點的距離相等, 則添加到一個集合中. 枚舉集合中的任意兩點,與對角線兩端點組成一個四邊形. 判斷該四邊形是否符合條件: 首先集合中兩點到對角線端點的距離要相等. 其次,這四點要不共面.
在上述判斷過程中會出現重復計數: 由於每個四邊形有兩條對角線,所以在枚舉對角形計數時,每個四邊形都被計數了兩次. 特殊的:如果一個四面體是正四面體,那么這四個點被計數了6次. (每條邊都計數一次) 所以在處理過程中要記錄出現了幾次正四面體. 每當枚舉到一個合法的空間四面體時,求一下剩下兩條邊是否跟其它邊相等. 如果相等則計數. 令rep為上述計數次數, rep/6 為正四面體的個數(每個正四面體會計數6次). 根據上述分析, ans/2 - 2*rep/6 即為最后結果.
關於時間復雜度: 上述過程看起來是 O(N^4). 而實際上,每次枚舉對角線時,符合條件的點一定在這條對角線的中垂面上. 所以不可能每次枚舉對角線時,都有很多點在中垂面上. 所以均攤復雜度並不高.

##代碼: ``` cpp #include #include #include #include #include #include #include #include #include #include #include #define LL long long #define double long long #define eps 1e-8 #define maxn 1010 #define mod 1000000007 #define inf 0x3f3f3f3f #define mid(a,b) ((a+b)>>1) #define IN freopen("in.txt","r",stdin); using namespace std;

int n;
struct Point{
double x,y,z;
Point(){}
Point(double tx,double ty) {x=tx;y=ty;}
}p[220];

double Distance(Point p1,Point p2)
{
return ((p1.x-p2.x)(p1.x-p2.x)+(p1.y-p2.y)(p1.y-p2.y)+(p1.z-p2.z)*(p1.z-p2.z));
}

Point xmul(Point u, Point v) {
Point ret;
ret.x = u.yv.z - v.yu.z;
ret.y = u.zv.x - u.xv.z;
ret.z = u.xv.y - u.yv.x;
return ret;
}

LL dmul(Point u, Point v) {
return u.xv.x + u.yv.y + u.z*v.z;
}

Point subt(Point u, Point v) {
Point ret;
ret.x = u.x - v.x;
ret.y = u.y - v.y;
ret.z = u.z - v.z;
return ret;
}
/求平面的垂向量/
Point pvec(Point s1, Point s2, Point s3) {
return xmul(subt(s1,s2),subt(s2,s3));
}

/判斷四點共面/
bool is_ok(Point a, Point b, Point c, Point d) {
return (dmul(pvec(a,b,c),subt(d,a))) == 0LL;
}

struct node {
int id;
LL dis;
node(){}
node(int tx,LL ty) {id=tx;dis=ty;}
};
vector q;

int main(int argc, char const *argv[])
{
//IN;

int t, ca=1; cin >> t;
while(t--)
{
    scanf("%d", &n);
    for(int i=1; i<=n; i++)
        scanf("%lld %lld %lld", &p[i].x, &p[i].y, &p[i].z);

    int ans = 0;
    int rep = 0;
    for(int i=1; i<=n; i++) {
        for(int j=i+1; j<=n; j++) {  /*枚舉對角線*/
            q.clear();
            for(int k=1; k<=n; k++) {
                if(Distance(p[k],p[i]) == Distance(p[k],p[j])) {
                    q.push_back(node(k, Distance(p[k],p[j])));
                }
            }

            int sz = q.size();
            for(int ii=0; ii<sz; ii++) {
                for(int jj=ii+1; jj<sz; jj++) {
                    if(q[ii].dis != q[jj].dis) continue;
                    if(is_ok(p[i],p[j],p[q[ii].id],p[q[jj].id])) continue;  /*四點共面*/
                    ans++;

                    /*是否是正四面體*/
                    if(Distance(p[i],p[j])==q[ii].dis && q[ii].dis==Distance(p[q[ii].id],p[q[jj].id]))
                        rep++;
                }
            }
        }
    }

    ans /= 2;
    ans -= 2*rep/6;

    printf("Case #%d: %d\n", ca++, ans);
}

return 0;

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM