• 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 }
  • 相关阅读:
    Docker之概述
    redis命令
    spring mvc(1) 为什么要使用mvc
    学习到的
    HttpWebRequest简单使用
    推手总结
    react 生命周期
    利用反射对应数据库字段
    扩展方法
    发送请求并返回
  • 原文地址:https://www.cnblogs.com/CSGrandeur/p/2659143.html
Copyright © 2020-2023  润新知