UVALive4973 CERC2010A Ardenia

分类讨论的情况不难想,难点在于判断各种垂线垂足是否在线段上。设bl1、bl2为两个线段上公垂线垂足位置的比例值,x为p0的公垂线垂足X坐标,则:

x = (p1.x - p0.x) * bl1 + p0.x

同理可得其他坐标。公垂线向量与两线段向量点积为0可得两个方程,求得bl1和bl2皆在0~1范围内则公垂线垂足都在线段上。

  1 #include<stdio.h>

  2 #include<stdlib.h>

  3 #include<string.h>

  4 typedef long long LL;

  5 const double eps = 1e-8;

  6 int dcmp(double d)

  7 {

  8     if(d < -eps) return -1;

  9     return d > eps ? 1 : 0;

 10 }

 11 struct Point3

 12 {

 13     Point3()

 14     {

 15         x = y = z = 0;

 16     }

 17     Point3(LL a, LL b, LL c)

 18     {

 19         x = a, y = b, z = c;

 20     }

 21     Point3 operator*(const Point3 &p)const

 22     {

 23         return Point3(y * p.z - z * p.y,

 24                       z * p.x - x * p.z,

 25                       x * p.y - y * p.x);

 26     }

 27     Point3 operator-(const Point3 &p)const

 28     {

 29         return Point3(x - p.x, y - p.y, z - p.z);

 30     }

 31     Point3 operator+(const Point3 &p)const

 32     {

 33         return Point3(x + p.x, y + p.y, z + p.z);

 34     }

 35     Point3 operator-()const

 36     {

 37         return Point3(-x, -y, -z);

 38     }

 39     LL dot(const Point3 &p)const

 40     {

 41         return x * p.x + y * p.y + z * p.z;

 42     }

 43     LL x, y, z;

 44 } p[4];

 45 LL gcd(LL a, LL b)

 46 {

 47     return b ? gcd(b, a % b) : a;

 48 }

 49 struct Dis

 50 {

 51     LL fz, fm;

 52     void yf()

 53     {

 54         if(fz == 0)

 55         {

 56             fm = 1;

 57             return;

 58         }

 59         LL t = gcd(fz, fm);

 60         fz /= t;

 61         fm /= t;

 62     }

 63     bool operator<(const Dis &p)const

 64     {

 65         return fz * p.fm < p.fz * fm;

 66     }

 67 };

 68 inline LL Sqr(LL a)

 69 {

 70     return a * a;

 71 }

 72 bool Paral(Point3 a, Point3 b, Point3 c, Point3 d)

 73 {

 74     Point3 tmp = (b - a) * (d - c);

 75     return !tmp.dot(tmp);

 76 }

 77 bool JudgeCZ(Point3 a, Point3 b, Point3 c, Point3 d)

 78 {

 79     LL A1, B1, C1, A2, B2, C2;

 80     A1 = (b - a).dot(b - a);

 81     B1 = -(d - c).dot(b - a);

 82     C1 = -(a - c).dot(b - a);

 83     A2 = (b - a).dot(d - c);

 84     B2 = -(d - c).dot(d - c);

 85     C2 = -(a - c).dot(d - c);

 86     double bl1 = dcmp(A2 * B1 - A1 * B2) ? ((double)C2 * B1 - C1 * B2) / (A2 * B1 - A1 * B2) : (A1 ? (double)C1 / A1 : (A2 ? (double)C2 / A2 : 0));

 87     double bl2 = dcmp(B2 * A1 - B1 * A2) ? ((double)C2 * A1 - C1 * A2) / (B2 * A1 - B1 * A2) : (B1 ? (double)C1 / B1 : (B2 ? (double)C2 / B2 : 0));

 88     return bl1 > -eps && bl1 < 1 + eps && bl2 > -eps && bl2 < 1 + eps;

 89 }

 90 Dis CalPtoL(Point3 p, Point3 a, Point3 b)

 91 {

 92     Point3 t = (a - p) * (b - a);

 93     Dis tmp;

 94     tmp.fz = t.dot(t);

 95     tmp.fm = (b - a).dot(b - a);

 96     tmp.yf();

 97     return tmp;

 98 }

 99 Dis CalPtoP(Point3 a, Point3 b)

100 {

101     Dis tmp;

102     tmp.fz = (b - a).dot(b - a);

103     tmp.fm = 1;

104     tmp.yf();

105     return tmp;

106 }

107 Dis min(Dis a, Dis b)

108 {

109     return a < b ? a : b;

110 }

111 int main()

112 {

113     int t, i;

114     Dis ans;

115     for(scanf("%d", &t); t -- ;)

116     {

117         ans.fz = 1, ans.fm = 0;

118         for(i = 0; i < 4; ++ i)

119             scanf("%lld%lld%lld", &p[i].x, &p[i].y, &p[i].z);

120         if(!Paral(p[0], p[1], p[2], p[3]) && JudgeCZ(p[0], p[1], p[2], p[3]))

121         {

122             Point3 t = (p[1] - p[0]) * (p[3] - p[2]);

123             ans.fz = Sqr((p[2] - p[0]).dot(t));

124             ans.fm = t.dot(t);

125             ans.yf();

126         }

127         else

128         {

129             if(JudgeCZ(p[0], p[0], p[2], p[3]))

130                 ans = min(ans, CalPtoL(p[0], p[2], p[3]));

131             if(JudgeCZ(p[1], p[1], p[2], p[3]))

132                 ans = min(ans, CalPtoL(p[1], p[2], p[3]));

133             if(JudgeCZ(p[0], p[1], p[2], p[2]))

134                 ans = min(ans, CalPtoL(p[2], p[0], p[1]));

135             if(JudgeCZ(p[0], p[1], p[3], p[3]))

136                 ans = min(ans, CalPtoL(p[3], p[0], p[1]));

137             ans = min(ans, CalPtoP(p[0], p[2]));

138             ans = min(ans, CalPtoP(p[0], p[3]));

139             ans = min(ans, CalPtoP(p[1], p[2]));

140             ans = min(ans, CalPtoP(p[1], p[3]));

141         }

142         printf("%lld %lld\n", ans.fz, ans.fm);

143     }

144     return 0;

145 }

你可能感兴趣的:(live)