uvalive 4973

来源:互联网 发布:怎样用淘宝客推广 编辑:程序博客网 时间:2024/06/06 04:58

题意:给出空间两条线段,求他们的最近距离的平方,要用分数形式表示 : l / m两个互质数 其中m>0。
题解:有两种情况,如果两条线段平行或重合,直接计算线段每个端点到另一条线段的距离,取最小值。否则就是异面直线,模板函数带入进行了。。。因为一个变量名坑了一下午加一晚上。。。而且存数字要用long long。。。

#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>using namespace std;long long gcd(long long a, long long b) {    return b == 0 ? a : gcd(b, a % b);}long long lcm(long long a, long long b) {    return a / gcd(a, b) * b;}struct Rat {    long long a, b;    Rat(long long a = 0):a(a), b(1) {}    Rat(long long x, long long y):a(x), b(y) {        if (b < 0) {            a = -a;            b = -b;        }        long long temp = gcd(a, b);        if (temp < 0)            temp = -temp;        a /= temp;        b /= temp;    }};Rat operator + (const Rat& A, const Rat& B) {    long long temp = lcm(A.b, B.b);    return Rat(A.a * (temp / A.b) + B.a * (temp / B.b), temp);}Rat operator - (const Rat& A, const Rat& B) {    return A + Rat(-B.a, B.b);}Rat operator * (const Rat& A, const Rat& B) {    return Rat(A.a * B.a, A.b * B.b);}void Min(Rat& A, const Rat& B) {    if (A.a * B.b > B.a * A.b) {        A.a = B.a;        A.b = B.b;    }}struct Point3 {    long long x, y, z;    Point3(long long x = 0, long long y = 0, long long z = 0):x(x), y(y), z(z) {}};typedef Point3 Vector3;Vector3 operator + (const Vector3& A, const Vector3& B) {    return Vector3(A.x + B.x, A.y + B.y, A.z + B.z);}Vector3 operator - (const Vector3& A, const Vector3& B) {    return Vector3(A.x - B.x, A.y - B.y, A.z - B.z);}Vector3 operator * (const Vector3& A, long long b) {    return Vector3(A.x * b, A.y * b, A.z * b);}bool operator == (const Point3& A, const Point3& B) {    return A.x == B.x && A.y == B.y && A.z == B.z;}long long Dot (const Vector3& A, const Vector3& B) {    return A.x * B.x + A.y * B.y + A.z * B.z;}long long Length(const Vector3& A) {    return Dot(A, A);}Vector3 Cross(const Vector3& A, const Vector3& B) {    return Vector3(A.y * B.z - A.z * B.y, A.z * B.x - A.x * B.z, A.x * B.y - A.y * B.x);}//点到线段距离Rat Rat_DistanceToSegment(const Point3& P, const Point3& A, const Point3& B) {    if (A == B)        return Rat(Length(P - A));    Vector3 v1 = B - A, v2 = P - A, v3 = P - B;    if (Dot(v1, v2) < 0)        return Rat(Length(v2));    if (Dot(v1, v3) > 0)        return Rat(Length(v3));    return Rat(Length(Cross(v1, v2)), Length(v1));}//求p1 + su和p2 + tv两个异面直线的公垂线,如果平行或重合返回false//两次调用解出t和s两个参数bool Rat_LineDistance3D(const Point3& p1, const Vector3& u, const Point3& p2, const Vector3& v, Rat& s) {    long long b = Dot(u, u) * Dot(v, v) - Dot(u, v) * Dot(u, v);    if (b == 0)        return false;    long long a = Dot(u, v) * Dot(v, p1 - p2) - Dot(v, v) * Dot(u, p1 - p2);    s = Rat(a, b);    return true;}void Rat_GetPointOnLine(const Point3& A, const Point3& B, const Rat& t, Rat& x, Rat& y, Rat& z) {    x = Rat(A.x) + Rat(B.x - A.x) * t;    y = Rat(A.y) + Rat(B.y - A.y) * t;    z = Rat(A.z) + Rat(B.z - A.z) * t;}int main() {    int cas;    scanf("%d", &cas);    while (cas--) {        Point3 L1[2], L2[2];        scanf("%lld%lld%lld%lld%lld%lld", &L1[0].x, &L1[0].y, &L1[0].z, &L1[1].x, &L1[1].y, &L1[1].z);        scanf("%lld%lld%lld%lld%lld%lld", &L2[0].x, &L2[0].y, &L2[0].z, &L2[1].x, &L2[1].y, &L2[1].z);        Rat res = Rat(1e9) s, t;        int flag = 0;        if (Rat_LineDistance3D(L1[0], L1[1] - L1[0], L2[0], L2[1] - L2[0], s)) {            if (s.a > 0 && s.a < s.b && Rat_LineDistance3D(L2[0], L2[1] - L2[0], L1[0], L1[1] - L1[0], t)) {                if (t.a > 0 && t.a < t.b) { //点要在线段上需要参数保证在0~1之间                    flag = 1;                    Rat x1, y1, z1, x2, y2, z2;                    Rat_GetPointOnLine(L1[0], L1[1], s, x1, y1, z1);                    Rat_GetPointOnLine(L2[0], L2[1], t, x2, y2, z2);                    res = Rat((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2));                }            }        }        if (!flag) {            Min(res, Rat_DistanceToSegment(L1[0], L2[0], L2[1]));            Min(res, Rat_DistanceToSegment(L1[1], L2[0], L2[1]));            Min(res, Rat_DistanceToSegment(L2[0], L1[0], L1[1]));            Min(res, Rat_DistanceToSegment(L2[1], L1[0], L1[1]));        }        if (res.a == 0)            res.b = 1;        printf("%lld %lld\n", res.a, res.b);    }    return 0;}
0 0
原创粉丝点击