这道题的题解网络上很少。
我来传一波。
这道题第一个难点是如何量化稳定这个定义。
稳定,翻译成数学语言就是这个点的重心在底面的投影在底面内。
知道这个,此题可破。
然后就是考虑这个形状的可能性。题目条件限制很强,直接分类讨论就可以。把外边六个面分成三个部分讨论:面ABD,面ABE为第一组,面BCD,面BCE为第二组,面ACD,面ACE为第三组。然后就是对于每组来讲,可以有组内两个面共面,组内两个面在整个图形中是凸的,组内两个面在整个图形中是凹的三种情况。需要注意的是,最多只可能有一组是共面的,但是组内两个面在整个图形中是凹的这种情况的组数可以不止一个。想明白这个问题,对于每组的三种情况分别讨论即可。以下是代码君:草草写了一个,为了看起来方便。实际上可以把每组的情况写成一个函数,调用就行了,能省不少代码量。
#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <cmath> #include <algorithm> #include <cstring> #include <vector> #include <sstream> #define eps 1e-8 #define pi acos(-1.0) using namespace std; struct point { double x, y, z; point(double x = 0, double y = 0, double z = 0) :x(x), y(y), z(z){} }; typedef point vec; int sgn(double x) { if (fabs(x) < eps) return 0; else if (x < 0) return -1; else return 1; } vec operator +(vec a, vec b) { return vec(a.x + b.x, a.y + b.y, a.z + b.z); } vec operator -(point a, point b) { return vec(a.x - b.x, a.y - b.y, a.z - b.z); } vec operator *(double p, vec a) { return vec(p*a.x, p*a.y, p*a.z); } vec operator /(vec a, double p) { return vec(a.x / p, a.y / p, a.z / p); } bool operator <(vec a, vec b) { if (sgn(a.x - b.x) < 0) return true; else if (sgn(a.x - b.x) == 0 && sgn(a.y - b.y) < 0) return true; else if (sgn(a.y - b.y) == 0 && sgn(a.z - b.z) < 0) return true; return false; } bool operator ==(vec a, vec b) { return sgn(a.x - b.x) == 0 && sgn(a.y - b.y) == 0 && sgn(a.z - b.z) == 0; } double dot(vec a, vec b) { return a.x*b.x + a.y*b.y + a.z*b.z; } double len(vec a) { return sqrt(dot(a, a)); } vec cross(vec a, vec b) { return vec(a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x); } double point2face(point p, point a, point b, point c) { double test1 = fabs(dot(cross(a - b, a - c), a - p)); double test2 = len(cross(a - b, a - c)); return fabs(dot(cross(a - b, a - c), a - p)) / len(cross(a - b, a - c)); } struct face { point a; point b; point c; point p; face(point a = point(0, 0, 0), point b = point(0, 0, 0), point c = point(0, 0, 0), point p = point(0, 0, 0)) :a(a), b(b), c(c), p(p){} }; bool operator <(face s, face t) { return point2face(s.p, s.a, s.b, s.c) < point2face(s.p, s.a, s.b, s.c); } bool fourpinaface(point a, point b, point c, point d) { if (sgn(len(cross(cross(a - b, a - c), cross(a - b, a - d)))) == 0) { return true; } else return false; } double volume(point a, point b, point c, point d) { return abs(dot(cross(a - b, a - c), a - d) / 6); } double point2line(point p, point a, point b) { double test1 = len(cross(p - a, b - a)); double test2 = len(b - a); return len(cross(p - a, b - a)) / len(b - a); } point honface(point p, point a, point b, point c) { vec n = cross(a - b, a - c); if (dot(p - a, n) < 0) n = vec(0, 0, 0) - n; n = n / len(n); double t = point2face(p, a, b, c); return p - t*n; } bool hintri(point h, point a, point b, point c)//包含边上,给四边形让路 { double test1 = len(cross(a - b, a - c)); double test2 = len(cross(h - a, h - b)); double test3 = len(cross(h - b, h - c)); double test4 = len(cross(h - c, h - a)); double test5 = test1 - test2 - test3 - test4; if (sgn(len(cross(a - b, a - c)) - len(cross(h - a, h - b)) - len(cross(h - b, h - c)) - len(cross(h - c, h - a))) == 0) return true; else return false; } bool isconcave(point A, point B, point C, point D, point E) { double test1 = dot(cross(B - A, C - A), D - A); double test2 = dot(cross(B - A, C - A), E - A); return dot(cross(B - A, C - A), D - A)*dot(cross(B - A, C - A), E - A) < 0; } vector<double>dist; int main(void) { point A, B, C, D, E, F;//B,D,E作为一个平面 int T = 0; while (scanf("%lf%lf%lf", &A.x, &A.y, &A.z) == 3) { dist.clear(); scanf("%lf %lf %lf", &B.x, &B.y, &B.z); scanf("%lf %lf %lf", &C.x, &C.y, &C.z); scanf("%lf %lf %lf", &D.x, &D.y, &D.z); scanf("%lf %lf %lf", &E.x, &E.y, &E.z); scanf("%lf %lf %lf", &F.x, &F.y, &F.z); T++; double V1 = volume(A, B, C, D); double V2 = volume(A, B, C, E); double sumv = V1 + V2; point sumg = V1 / 4 * (A + B + C + D) + V2*(A + B + C + E) / 4; point G = sumg / sumv; if (isconcave(D, B, A, E, C) == true) { point h = honface(G, B, D, E); if (hintri(h, B, D, E) == true)//在边上应该是可以的吧 { if (point2line(h, B, D) >= 0.2&&point2line(h, D, E) >= 0.2&&point2line(h, E, B) >= 0.2) { dist.push_back(point2face(F, B, D, E)); } } h = honface(G, A, D, E); if (hintri(h, A, D, E) == true) { if (point2line(h, A, D) >= 0.2&&point2line(h, D, E) >= 0.2&&point2line(h, E, A) >= 0.2) { dist.push_back(point2face(F, A, D, E)); } } } else if (fourpinaface(A, B, D, E) == true)//在某个三角形内,但是要找四个边的判断,不能简单的跟凹面合并!!! { point h = honface(G, B, D, E); if (hintri(h, B, D, E) == true) { if (point2line(h, B, D) >= 0.2&&point2line(h, A, E) >= 0.2&&point2line(h, A, D) >= 0.2&&point2line(h, E, B) >= 0.2) { dist.push_back(point2face(F, B, D, E)); } } h = honface(G, A, D, E); if (hintri(h, A, D, E) == true) { if (point2line(h, B, D) >= 0.2&&point2line(h, A, E) >= 0.2&&point2line(h, A, D) >= 0.2&&point2line(h, E, B) >= 0.2) { dist.push_back(point2face(F, A, D, E)); } } } else { point h = honface(G, A, B, E); if (hintri(h, A, B, E) == true) { if (point2line(h, A, B) >= 0.2&&point2line(h, B, E) >= 0.2&&point2line(h, E, A) >= 0.2) { dist.push_back(point2face(F, A, B, E)); } } h = honface(G, A, B, D); if (hintri(h, A, B, D) == true) { if (point2line(h, A, B) >= 0.2&&point2line(h, B, D) >= 0.2&&point2line(h, D, A) >= 0.2) { dist.push_back(point2face(F, A, B, D)); } } } if (isconcave(D, B, C, A, E) == true) { point h = honface(G, B, D, E); if (hintri(h, B, D, E) == true) { if (point2line(h, B, D) >= 0.2&&point2line(h, D, E) >= 0.2&&point2line(h, E, B) >= 0.2) { dist.push_back(point2face(F, B, D, E)); } } h = honface(G, C, D, E); if (hintri(h, C, D, E) == true) { if (point2line(h, C, D) >= 0.2&&point2line(h, D, E) >= 0.2&&point2line(h, E, C) >= 0.2) { dist.push_back(point2face(F, C, D, E)); } } } else if (fourpinaface(B, C, D, E) == true) { point h = honface(G, B, D, E); if (hintri(h, B, D, E) == true) { if (point2line(h, B, D) >= 0.2&&point2line(h, C, E) >= 0.2&&point2line(h, C, D) >= 0.2&&point2line(h, E, B) >= 0.2) { dist.push_back(point2face(F, B, D, E)); } } h = honface(G, C, D, E); if (hintri(h, C, D, E) == true) { if (point2line(h, B, D) >= 0.2&&point2line(h, C, E) >= 0.2&&point2line(h, C, D) >= 0.2&&point2line(h, E, B) >= 0.2) { dist.push_back(point2face(F, C, D, E)); } } } else { point h = honface(G, B, C, E); double test = dot(cross(B - C, B - E), B - h); if (hintri(h, B, C, E) == true) { if (point2line(h, B, C) >= 0.2&&point2line(h, C, E) >= 0.2&&point2line(h, E, B) >= 0.2) { dist.push_back(point2face(F, B, C, E)); } } h = honface(G, B, C, D); if (hintri(h, B, C, D) == true) { if (point2line(h, B, C) >= 0.2&&point2line(h, C, D) >= 0.2&&point2line(h, D, B) >= 0.2) { dist.push_back(point2face(F, B, C, D)); } } } if (isconcave(D, A, C, B, E) == true) { point h = honface(G, A, D, E); if (hintri(h, A, D, E) == true) { if (point2line(h, A, D) >= 0.2&&point2line(h, D, E) >= 0.2&&point2line(h, E, A) >= 0.2) { dist.push_back(point2face(F, A, D, E)); } } h = honface(G, C, D, E); if (hintri(h, C, D, E) == true) { if (point2line(h, C, D) >= 0.2&&point2line(h, D, E) >= 0.2&&point2line(h, E, C) >= 0.2) { dist.push_back(point2face(F, C, D, E)); } } } else if (fourpinaface(A, C, D, E) == true) { point h = honface(G, A, D, E); if (hintri(h, A, D, E) == true) { if (point2line(h, A, D) >= 0.2&&point2line(h, C, E) >= 0.2&&point2line(h, C, D) >= 0.2&&point2line(h, A, E) >= 0.2) { dist.push_back(point2face(F, A, D, E)); } } h = honface(G, C, D, E); if (hintri(h, C, D, E) == true) { if (point2line(h, A, D) >= 0.2&&point2line(h, C, E) >= 0.2&&point2line(h, C, D) >= 0.2&&point2line(h, E, A) >= 0.2) { dist.push_back(point2face(F, C, D, E)); } } } else { point h = honface(G, A, C, E); double test = dot(cross(A - C, A - E), A - h); if (hintri(h, A, C, E) == true) { if (point2line(h, A, C) >= 0.2&&point2line(h, C, E) >= 0.2&&point2line(h, E, A) >= 0.2) { dist.push_back(point2face(F, A, C, E)); } } h = honface(G, A, C, D); if (hintri(h, A, C, D) == true) { if (point2line(h, A, C) >= 0.2&&point2line(h, C, D) >= 0.2&&point2line(h, D, A) >= 0.2) { dist.push_back(point2face(F, A, C, D)); } } } sort(dist.begin(), dist.end()); printf("Case %d: %.5lf %.5lf\n", T, dist[0], dist[dist.size() - 1]); } return 0; }