zoukankan      html  css  js  c++  java
  • ACM/ICPC 之 三维计算几何+暴力枚举+判重(HDU5839)

    CCPC网赛第八题,求立体几何数量,题解见注释

    //立体几何-求满足要求的四面体个数
    //要求1:至少4条边相等
    //要求2:四条边相等时,另两条边一定不相邻(即对边)
    //题解:以当前边为不相邻的其中一条边,对可以构成等腰三角形的第三点进行枚举
    //再对这些第三点的集合做一次n^2的枚举,分两种情况找出四面体
    //如果四条边或五条边相同,则只存在两种重复情况(当前边和对边互换)
    //如果六条边相同,则存在六种重复情况(每个边作一次当前边)
    //Time:499Ms	Memory:1576K
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    
    #define MAXP 205
    #define POW(x) ((x)*(x))
    
    struct Point{
    	int x, y, z;
    	Point() {}
    	Point(int xx, int yy, int zz):x(xx), y(yy), z(zz){}
    }p[MAXP];
    
    struct Node {
    	int d, u;
    	Node(){}
    	Node(int dd, int uu):d(dd), u(uu){}
    }nd[MAXP];
    
    int n;
    int len;
    
    int Distance(Point a, Point b)
    {
    	return POW(a.x - b.x) + POW(a.y - b.y) + POW(a.z - b.z);
    }
    
    Point xmult(Point a, Point b) //叉积
    {
    	return Point(a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x);
    }
    //向量差a-b(b到a)
    Point subt(Point a, Point b)
    {
    	return Point(a.x - b.x, a.y - b.y, a.z - b.z);
    }
    
    int dmult(Point a, Point b)	//点积
    {
    	return a.x*b.x + a.y*b.y + a.z*b.z;
    }
    
    //取平面法向量
    Point normalv(Point a, Point b, Point c)
    {
    	return xmult(subt(a, b), subt(b, c));
    }
    
    bool onplane(Point a, Point b, Point c, Point d)	//四点共面
    {
    	return dmult(normalv(a, b, c), subt(d, a)) == 0;
    }
    
    int main()
    {
    	//freopen("t.in", "r", stdin);
    	int T;
    	int cas = 1;
    	scanf("%d", &T);
    	while (T--) {
    		scanf("%d", &n);
    		for (int i = 0; i < n; i++)
    			scanf("%d%d%d", &p[i].x, &p[i].y, &p[i].z);
    		int sum1 = 0, sum2 = 0;	//sum1:六条边不全相等,sum2:六条边都相等
    		for (int i = 0; i < n; i++)
    		{
    			for (int j = i + 1; j < n; j++)
    			{
    				len = 0;
    				for (int k = 0; k < n; k++)	//枚举到ij线段上距离相等的第三点k
    				{
    					if (k == i || k == j) continue;
    					int tmp = Distance(p[i], p[k]);
    					if (tmp == Distance(p[j], p[k]))
    						nd[len++] = Node(tmp, k);
    				}
    				
    				for (int k1 = 0; k1 < len; k1++)
    				{
    					for (int k2 = k1 + 1; k2 < len; k2++)
    					{
    						if (nd[k1].d != nd[k2].d) continue;
    						if (onplane(p[i], p[j], p[nd[k1].u], p[nd[k2].u])) continue;
    						int tmp = Distance(p[nd[k1].u], p[nd[k2].u]);
    						if (tmp == Distance(p[i], p[j])	&& tmp == nd[k1].d)
    							sum2++;	//六条边相等
    						else sum1++;
    					}
    				}
    
    			}
    		}
    		printf("Case #%d: %d
    ", cas++, sum1/2+sum2/6);
    	}
    
    	return 0;
    }
    
  • 相关阅读:
    (一)Redis初学教程之安装篇
    Redis常用数据类型
    css
    js常用内置对象、Dom对象、BOM对象
    CSS定位(postion)和移动(float)
    Razor模板引擎(C#版)语法
    虚拟化和反序列化
    id 自增------删除数据后恢复到删除前自增id
    SERVER全局数组
    文件路径操作
  • 原文地址:https://www.cnblogs.com/Inkblots/p/5771507.html
Copyright © 2011-2022 走看看