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\n", cas++, sum1/2+sum2/6); } return 0; }
他坐在湖边,望向天空,她坐在对岸,盯着湖面