diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..723ef36 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea \ No newline at end of file diff --git a/geometry.cpp b/geometry.cpp new file mode 100644 index 0000000..11e2cb1 --- /dev/null +++ b/geometry.cpp @@ -0,0 +1,49 @@ +#include "geometry.h" +#include +#include "ternary_search.h" + +Point::Point(double a, double b, double c) : x (a), y (b), z (c) {} + +Point::Point() : x (0), y (0), z (0) {} + +Segment::Segment (const Point& a, const Point& b) { + one = a; + two = b; +} + + +// расстояние между точками +const double getDistance(const Point& one, const Point& two) { + return sqrt(pow((one.x - two.x), 2) + pow((one.y - two.y), 2) + pow((one.z - two.z), 2)); +} + +Point operator+(const Point& one, const Point& two) { + return Point(one.x + two.x, one.y + two.y, one.z + two.z); +} + +Point operator*(const Point& p, double mult) { + return Point(p.x * mult, p.y * mult, p.z * mult); +} + +Point operator/(const Point& p, double mult) { + return Point(p.x / mult, p.y / mult, p.z / mult); +} + +double getDistancePointToSegment(const Point& p, const Segment& seg, double eps) { + auto func = [&p](const Point& p_to) { + return getDistance(p_to, p); + }; + // 1ый аргумент - точка, до которой кратчайшее растояние от p, 2ой - p + Point least_p_in_seg = ternarySearchMin(seg.one, seg.two, func, getDistance, eps); + return getDistance(least_p_in_seg, p); +} + + +double getDistanceSegmentToSegment(const Segment& seg1, const Segment& seg2, double eps) { + auto func = [&seg2](const Point& p_to) { + return getDistancePointToSegment(p_to, seg2); + }; + // 1ый аргумент - точка, до которой кратчайшее растояние от p, 2ой - p + Point x = ternarySearchMin(seg1.one, seg1.two, func, getDistance, eps); + return getDistancePointToSegment(x, seg2); +} diff --git a/geometry.h b/geometry.h new file mode 100644 index 0000000..347c2b8 --- /dev/null +++ b/geometry.h @@ -0,0 +1,34 @@ +#ifndef INC_3TERM_CONTESTS_GEOMETRY_H +#define INC_3TERM_CONTESTS_GEOMETRY_H + + +struct Point { + double x, y, z; + + Point (double a, double b, double c); + + Point (); +}; + +struct Segment { + Point one, two; + + Segment (const Point& a, const Point& b); +}; + + +// расстояние между точками +const double getDistance(const Point& one, const Point& two); + +Point operator+(const Point& one, const Point& two); + +Point operator*(const Point& p, double mult); + +Point operator/(const Point& p, double mult); + +double getDistancePointToSegment(const Point& p, const Segment& seg, double eps = 0.0000001); + +double getDistanceSegmentToSegment(const Segment& seg1, const Segment& seg2, double eps = 0.0000001); + + +#endif //INC_3TERM_CONTESTS_GEOMETRY_H diff --git a/mod3_a.cpp b/mod3_a.cpp new file mode 100644 index 0000000..8899794 --- /dev/null +++ b/mod3_a.cpp @@ -0,0 +1,31 @@ +/* + * Даны два отрезка в пространстве (x1, y1, z1) - (x2, y2, z2) и (x3, y3, z3) - (x4, y4, z4). + * Найдите расстояние между отрезками. + * + * */ + + +#include +#include +#include +#include "geometry.h" + + +int main() { + int x, y, z; + + std::cin >> x >> y >> z; + Point a (x, y, z); + std::cin >> x >> y >> z; + Point b (x, y, z); + std::cin >> x >> y >> z; + Point c (x, y, z); + std::cin >> x >> y >> z; + Point d (x, y, z); + + Segment seg1 (c, d); + Segment seg2 (a, b); + + printf("%.9lf", getDistanceSegmentToSegment(seg1, seg2)); + return 0; +} diff --git a/ternary_search.h b/ternary_search.h new file mode 100644 index 0000000..965c2a6 --- /dev/null +++ b/ternary_search.h @@ -0,0 +1,20 @@ +#ifndef INC_3TERM_CONTESTS_TERNARY_SEARCH_H +#define INC_3TERM_CONTESTS_TERNARY_SEARCH_H + + +template +T ternarySearchMin(T left, T right, Func f, const double (*getDistance)(const T&, const T&), double eps = 0.0000001) { + while (getDistance(left, right) > eps) { + T a = (left * 2 + right) / 3; + T b = (left + right * 2) / 3; + if (f(a) < f(b)) { + right = b; + } else { + left = a; + } + } + return (left + right) / 2; +} + + +#endif //INC_3TERM_CONTESTS_TERNARY_SEARCH_H