码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 5839 Special Tetrahedron

时间:2016-08-14 20:45:21      阅读:137      评论:0      收藏:0      [点我收藏+]

标签:

  大神说是水题,可我小白;

  题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5839

  题意:给n个不重且为正数点(范围2000),问满足题意的四个点的组数;

     条件1:四个点可以构成一个四面体,并且最少有四个边相等;2:如果仅有四个边相等,不相等的两边不相邻;

  想法:四面体有四条边相等,即在相等的边里找符合要求的四点,把三维的点转化为边,边长度排序,即得相等的边在一块线性处理,在相等的边里枚举符合条件的组合数,

并且去重,即得答案。

  代码:


#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
using namespace std;

struct tt     //结构体保存点的下标和两点的长度的平方(整形没误差);
{
    int len;
    int x,y;
} p[200*200];

bool cmp(const tt &a,const tt &b)
{
    return a.len < b.len;
}
int m[222][3];      //  原始数据数组;
int le(int i,int j)    //   求两点的长度;
{
    return (m[i][0] - m[j][0])*(m[i][0] - m[j][0]) +
           (m[i][1] - m[j][1])*(m[i][1] - m[j][1])+
           (m[i][2] - m[j][2])*(m[i][2] - m[j][2]);
}


struct point           //   判断四点是否共面,后期用的模板,所以加了相应的结构,可优化;
{
    int x,y,z;
} px[5];
bool isok(int a1,int a2,int a3,int a4)      // 判断四点是否共面;
{
    px[0].x = m[a1][0],px[0].y = m[a1][1],px[0].z = m[a1][2];
    px[1].x = m[a2][0],px[1].y = m[a2][1],px[1].z = m[a2][2];
    px[2].x = m[a3][0],px[2].y = m[a3][1],px[2].z = m[a3][2];
    px[3].x = m[a4][0],px[3].y = m[a4][1],px[3].z = m[a4][2];

    int t,i,ans;
    point s1,s2,s3;

    s1.x=px[1].x-px[0].x;
    s1.y=px[1].y-px[0].y;
    s1.z=px[1].z-px[0].z;
    s2.x=px[2].x-px[0].x;
    s2.y=px[2].y-px[0].y;
    s2.z=px[2].z-px[0].z;
    s3.x=px[3].x-px[0].x;
    s3.y=px[3].y-px[0].y;
    s3.z=px[3].z-px[0].z;
    ans=s1.x*s2.y*s3.z+s1.y*s2.z*s3.x+s1.z*s2.x*s3.y-s1.z*s2.y*s3.x-s1.x*s2.z*s3.y-s1.y*s2.x*s3.z;
    if(ans==0) return true;
    else return false;



}
struct has                //为用set去重加的数据结构,小白,set数据结构不熟,不懂自己百度;
{
    int  index[4];
    bool     operator < (const has &x)const
    {
        if(index[0]==x.index[0])
        {
            if(index[1]==x.index[1])
            {
                if(index[2]==x.index[2])
                {
                    if(index[3]==x.index[3])
                    {
                        return index[3]<x.index[3];
                    }
                    else return index[3]<x.index[3];
                }
                else return index[2]<x.index[2];
            }
            else return index[1]<x.index[1];
        }
        else return index[0]<x.index[0];
    }
};
set<has> vis;

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int t,cas = 1;
    cin>>t;
    while(t--)
    {
        vis.clear();
        int n;
        cin>>n;
        for(int i=0; i<n; i++)
        {
            cin>>m[i][0]>>m[i][1]>>m[i][2];
        }
        int q=0;
        for(int i=0; i<n; i++)        
        {
            for(int j=i+1; j<n; j++)
            {
                p[q].len=le(i,j);
                p[q].x = i;
                p[q++].y = j;
            }

        }
        long long ans = 0;
        sort(p,p+q,cmp);          //排序,这个很重要;
        for(int i =0; i<q; i++)
        {
            tt p1 = p[i];
            for(int j = i+1; p1.len == p[j].len; j++)           //其中的条件是因为不相等就没有枚举的必要;
            {
                tt p2 = p[j];
                if(isok(p1.x,p1.y,p2.x,p2.y)) continue;    //共面成形,不成体;

                if(p1.x !=p2.y && p2.x != p1.y)    //去掉有重点的边,因为我是要枚举两条相等的对边,再判断;
                {
                    int len1 = le(p1.x,p2.x);
                    int len2 = le(p1.x,p2.y);
                    if(len1 == le(p1.y,p2.y) && len1 == p1.len)    //四条边相等,又分两种情况,下面的存排,目的去重;
                    {
                        has aa;
                        aa.index[0] = p1.x;
                        aa.index[1] = p1.y;
                        aa.index[2] = p2.x;
                        aa.index[3] = p2.y;
                        sort(aa.index,aa.index+4);
                        if(vis.count(aa) != 1)
                        {
                            vis.insert(aa);
                            ans++;
                        }

                    }
                    else if( len2== le(p1.y,p2.x) && len2 == p2.len)
                    {
                        has aa;
                        aa.index[0] = p1.x;
                        aa.index[1] = p1.y;
                        aa.index[2] = p2.x;
                        aa.index[3] = p2.y;
                        sort(aa.index,aa.index+4);
                        if(vis.count(aa) != 1)
                        {
                            vis.insert(aa);
                            ans++;
                        }
                    }

                }
            }

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

    }
    return 0;
}

     总结:枚举四个点,不现实,可以转化为边再枚举,并加优化;

hdu 5839 Special Tetrahedron

标签:

原文地址:http://www.cnblogs.com/aishuijdemiaomiao/p/5770791.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!