• LA 4973 Ardenia (3D Geometry + Simulation)


    ACM-ICPC Live Archive

      三维几何,题意是要求求出两条空间线段的距离。题目难度在于要求用有理数的形式输出,这就要求写一个有理数类了。

      开始的时候写出来的有理数类就各种疯狂乱套,TLE的结果是显然的。后来发现,在计算距离前都是不用用到有理数类的,所以就将开始的部分有理数改成直接用long long。其实好像可以用int来做的,不过我的方法比较残暴,中间运算过程居然爆int了。所以就只好用long long了。

    代码如下,附带debug以及各种强的数据:

      1 #include <cstdio>
      2 #include <iostream>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <cmath>
      6 
      7 using namespace std;
      8 
      9 template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a;}
     10 template <class T> T sqr(T x) { return x * x;}
     11 typedef long long LL;
     12 struct Rat {
     13     LL a, b;
     14     Rat() {}
     15     Rat(LL x) { a = x, b = 1;}
     16     Rat(LL _a, LL _b) {
     17         LL GCD = gcd(_b, _a);
     18         a = _a / GCD, b = _b / GCD;
     19     }
     20     double val() { return (double) a / b;}
     21     bool operator < (Rat x) const { return a * x.b < b * x.a;}
     22     bool operator > (Rat x) const { return a * x.b > b * x.a;}
     23     bool operator == (Rat x) const { return a * x.b == b * x.a;}
     24     bool operator < (LL x) const { return Rat(a, b) < Rat(x);}
     25     bool operator > (LL x) const { return Rat(a, b) > Rat(x);}
     26     bool operator == (LL x) const { return Rat(a, b) == Rat(x);}
     27     Rat operator + (Rat x) {
     28         LL tb = b * x.b, ta = a * x.b + b * x.a;
     29         LL GCD = gcd(abs(tb), abs(ta));
     30         return Rat(ta / GCD, tb / GCD);
     31     }
     32     Rat operator - (Rat x) {
     33         LL tb = b * x.b, ta = a * x.b - b * x.a;
     34         LL GCD = gcd(abs(tb), abs(ta));
     35         return Rat(ta / GCD, tb / GCD);
     36     }
     37     Rat operator * (Rat x) {
     38         if (a * x.a == 0) return Rat(0, 1);
     39 //        if (b * x.b == 0) { puts("..."); while (1) ;}
     40         LL tb = b * x.b, ta = a * x.a;
     41         LL GCD = gcd(abs(tb), abs(ta));
     42         return Rat(ta / GCD, tb / GCD);
     43     }
     44     Rat operator / (Rat x) {
     45         if (a * x.b == 0) return Rat(0, 1);
     46 //        if (b * x.a == 0) { puts("!!!"); while (1) ;}
     47         LL GCD, tb = b * x.a, ta = a * x.b;
     48         GCD = gcd(abs(tb), abs(ta));
     49         return Rat(ta / GCD, tb / GCD);
     50     }
     51     void fix() {
     52         a = abs(a), b = abs(b);
     53         LL GCD = gcd(b, a);
     54         a /= GCD, b /= GCD;
     55     }
     56 } ;
     57 
     58 struct Point {
     59     LL x[3];
     60     Point operator + (Point a) {
     61         Point ret;
     62         for (int i = 0; i < 3; i++) ret.x[i] = x[i] + a.x[i];
     63         return ret;
     64     }
     65     Point operator - (Point a) {
     66         Point ret;
     67         for (int i = 0; i < 3; i++) ret.x[i] = x[i] - a.x[i];
     68         return ret;
     69     }
     70     Point operator * (LL p) {
     71         Point ret;
     72         for (int i = 0; i < 3; i++) ret.x[i] = x[i] * p;
     73         return ret;
     74     }
     75     bool operator == (Point a) const {
     76         for (int i = 0; i < 3; i++) if (!(x[i] == a.x[i])) return false;
     77         return true;
     78     }
     79     void print() {
     80         for (int i = 0; i < 3; i++) cout << x[i] << ' ';
     81         cout << endl;
     82     }
     83 } ;
     84 typedef Point Vec;
     85 
     86 struct Line {
     87     Point s, t;
     88     Line() {}
     89     Line (Point s, Point t) : s(s), t(t) {}
     90     Vec vec() { return t - s;}
     91 } ;
     92 typedef Line Seg;
     93 
     94 LL dotDet(Vec a, Vec b) {
     95     LL ret = 0;
     96     for (int i = 0; i < 3; i++) ret = ret + a.x[i] * b.x[i];
     97     return ret;
     98 }
     99 
    100 Vec crossDet(Vec a, Vec b) {
    101     Vec ret;
    102     for (int i = 0; i < 3; i++) {
    103         ret.x[i] = a.x[(i + 1) % 3] * b.x[(i + 2) % 3] - a.x[(i + 2) % 3] * b.x[(i + 1) % 3];
    104     }
    105     return ret;
    106 }
    107 
    108 inline LL vecLen(Vec x) { return dotDet(x, x);}
    109 inline bool parallel(Line a, Line b) { return vecLen(crossDet(a.vec(), b.vec())) == 0;}
    110 inline bool onSeg(Point x, Point a, Point b) { return parallel(Line(a, x), Line(b, x)) && dotDet(a - x, b - x) < 0;}
    111 inline bool onSeg(Point x, Seg s) { return onSeg(x, s.s, s.t);}
    112 
    113 Rat pt2Seg(Point p, Point a, Point b) {
    114     if (a == b) return Rat(vecLen(p - a));
    115     Vec v1 = b - a, v2 = p - a, v3 = p - b;
    116     if (dotDet(v1, v2) < 0) return Rat(vecLen(v2));
    117     else if (dotDet(v1, v3) > 0) return Rat(vecLen(v3));
    118     else return Rat(vecLen(crossDet(v1, v2)), vecLen(v1));
    119 }
    120 inline Rat pt2Seg(Point p, Seg s) { return pt2Seg(p, s.s, s.t);}
    121 inline Rat pt2Plane(Point p, Point p0, Vec n) { return Rat(sqr(dotDet(p - p0, n)), vecLen(n));}
    122 inline bool segIntersect(Line a, Line b) {
    123     Vec v1 = crossDet(a.s - b.s, a.t - b.s);
    124     Vec v2 = crossDet(a.s - b.t, a.t - b.t);
    125     Vec v3 = crossDet(b.s - a.s, b.t - a.s);
    126     Vec v4 = crossDet(b.s - a.t, b.t - a.t);
    127 //    v1.print();
    128 //    v2.print();
    129 //    cout << dotDet(v1, v2).val() << "= =" << endl;
    130     return dotDet(v1, v2) < 0 && dotDet(v3, v4) < 0;
    131 }//        cout << "same plane" << endl;
    132 
    133 pair<Rat, Rat> getIntersect(Line a, Line b) {
    134     Point p = a.s, q = b.s;
    135     Vec v = a.vec(), u = b.vec();
    136     LL uv = dotDet(u, v), vv = dotDet(v, v), uu = dotDet(u, u);
    137     LL pv = dotDet(p, v), qv = dotDet(q, v), pu = dotDet(p, u), qu = dotDet(q, u);
    138     if (uv == 0) return make_pair(Rat(qv - pv, vv), Rat(pu - qu, uu));
    139 //    if (vv == 0 || uv == 0 || uv / vv - uu / uv == 0) { puts("shit!"); while (1) ;}
    140     Rat y = (Rat(pv - qv, vv) - Rat(pu - qu, uv)) / (Rat(uv, vv) - Rat(uu, uv));
    141     Rat x = (y * uv - pv + qv) / vv;
    142 //    cout << x.a << ' ' << x.b << ' ' << y.a << ' ' << y.b << endl;
    143     return make_pair(x, y);
    144 }
    145 
    146 void work(Point *pt) {
    147     Line a = Line(pt[0], pt[1]);
    148     Line b = Line(pt[2], pt[3]);
    149     if (parallel(a, b)) {
    150         if (onSeg(pt[0], b) || onSeg(pt[1], b)) { puts("0 1"); return ;}
    151         if (onSeg(pt[2], a) || onSeg(pt[3], a)) { puts("0 1"); return ;}
    152 //        cout << "parallel" << endl;
    153         Rat tmp = min(min(pt2Seg(pt[0], b), pt2Seg(pt[1], b)), min(pt2Seg(pt[2], a), pt2Seg(pt[3], a)));
    154         tmp.fix();
    155         printf("%lld %lld
    ", tmp.a, tmp.b);
    156         return ;
    157     }
    158     Vec nor = crossDet(a.vec(), b.vec());
    159     Rat ans = pt2Plane(pt[0], pt[2], nor);
    160 //    cout << "~~~" << endl;
    161     if (ans == 0) {
    162 //        cout << "same plane" << endl;
    163         if (segIntersect(a, b)) { puts("0 1"); return ;}
    164         Rat tmp = min(min(pt2Seg(pt[0], b), pt2Seg(pt[1], b)), min(pt2Seg(pt[2], a), pt2Seg(pt[3], a)));
    165         tmp.fix();
    166         printf("%lld %lld
    ", tmp.a, tmp.b);
    167         return ;
    168     } else {
    169 //        cout << "diff plane" << endl;
    170         pair<Rat, Rat> tmp = getIntersect(a, b);
    171 //        cout << tmp.first.val() << "= =" << tmp.second.val() << endl;
    172 //        cout << (tmp.first > 0) << endl;
    173         if (tmp.first > 0 && tmp.first < 1 && tmp.second > 0 && tmp.second < 1) {
    174 //            cout << "cross" << endl;
    175             ans.fix();
    176             printf("%lld %lld
    ", ans.a, ans.b);
    177         } else {
    178 //            cout << "not cross" << endl;
    179             Rat t = min(min(pt2Seg(pt[0], b), pt2Seg(pt[1], b)), min(pt2Seg(pt[2], a), pt2Seg(pt[3], a)));
    180             t.fix();
    181             printf("%lld %lld
    ", t.a, t.b);
    182         }
    183     }
    184 }
    185 
    186 int main() {
    187 //    freopen("in", "r", stdin);
    188 //    freopen("out", "w", stdout);
    189     Point pt[4];
    190     int T;
    191     cin >> T;
    192     while (T--) {
    193         for (int i = 0; i < 4; i++) {
    194             for (int j = 0; j < 3; j++) {
    195                 scanf("%lld", &pt[i].x[j]);
    196             }
    197         }
    198         work(pt);
    199     }
    200     return 0;
    201 }
    202 
    203 /*
    204 13
    205 
    206 -20 -20 -20 20 20 19
    207 0 0 0 1 1 1
    208 
    209 -20 -20 -20 20 19 20
    210 -20 -20 20 20 20 -20
    211 
    212 0 0 0 20 20 20
    213 0 0 10 0 20 10
    214 
    215 0 0 0 1 1 1
    216 2 3 4 1 2 2
    217 
    218 0 0 0 0 0 0
    219 0 1 1 1 2 3
    220 
    221 0 0 0 10 10 10
    222 11 12 13 10 11 11
    223 
    224 0 0 0 1 1 1
    225 1 1 1 2 2 2
    226 
    227 1 0 0 0 1 0
    228 1 1 0 2 2 0
    229 
    230 1 0 0 0 1 0
    231 0 0 0 1 1 0
    232 
    233 0 0 0 0 0 20
    234 20 0 10 0 20 10
    235 
    236 0 0 0 20 20 20
    237 1 1 2 1 1 2
    238 
    239 0 0 0 20 20 20
    240 0 20 20 0 20 20
    241 
    242 0 0 0 0 0 20
    243 20 20 0 20 20 20
    244 */
    View Code

    ——written by Lyon

  • 相关阅读:
    二分查找练习
    Linux中Buffer和Cache的区别
    c++设计模式之单例模式
    c++设计模式之工厂模式
    C++中内存泄漏的几种情况
    snprintf
    命名空间和模块化编程1
    避免内存泄漏
    静态对象强制类型转换
    副本构造器
  • 原文地址:https://www.cnblogs.com/LyonLys/p/LA_4973_Lyon.html
Copyright © 2020-2023  润新知