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
- uvalive 4973
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- UVALive
- zoj 3882 Help Bob(博弈)
- 循环、数组截取、随机数的产生(2015/7/30)
- STL学习记录(十四):其它几种算法
- VS2010关于error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
- ARM处理器体系架构详细说明
- uvalive 4973
- Scala学习第五天:数组的基本操作,数组的进阶操作和多维数组
- Hdu 1789 Doing Homework again
- pycharm快捷键、常用设置、包管理
- Selenium IDE简介
- linux驱动中宏__setup(str, fn)
- uva11235 Frequent values(线段树区间合并)
- 黑马程序员——String类
- dsp之BF531笔记