uvalive 4973
2015-07-31 21:26
253 查看
题意:给出空间两条线段,求他们的最近距离的平方,要用分数形式表示 : l / m两个互质数 其中m>0。
题解:有两种情况,如果两条线段平行或重合,直接计算线段每个端点到另一条线段的距离,取最小值。否则就是异面直线,模板函数带入进行了。。。因为一个变量名坑了一下午加一晚上。。。而且存数字要用long long。。。
题解:有两种情况,如果两条线段平行或重合,直接计算线段每个端点到另一条线段的距离,取最小值。否则就是异面直线,模板函数带入进行了。。。因为一个变量名坑了一下午加一晚上。。。而且存数字要用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; }
相关文章推荐
- 初级Javascript(一)
- Hdu 1789 Doing Homework again
- linux驱动中宏__setup(str, fn)
- 循环、数组截取、随机数的产生(2015/7/30)
- Selenium IDE简介
- ARM处理器体系架构详细说明
- 黑马程序员-C语言printf和scanf函数中格式控制符使用小结
- 黑马程序员——String类
- dsp之BF531笔记
- linux c++ 高并发tcp服务器架构
- 二分检索的多种应用
- SSH开发——菜鸟那些事儿
- hdu5064 DLX可重复覆盖+二分
- Qt实战之开发CSDN下载助手 (3)(结束篇)
- hdu 3342 Legal or Not(拓扑)
- POJ3258—River Hopscotch—二分法求the largest mimmun
- 多表连接
- [Linux] xargs
- Balanced Lineup---poj3264线段树基础
- 背包问题