Advertisement
DasShelmer

10.1.19

Dec 12th, 2019
184
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.15 KB | None | 0 0
  1. #include <iostream>
  2. #include <string>
  3. #include <fstream>
  4. #include <iomanip>
  5. #include <math.h>
  6. using namespace std;
  7.  
  8. // Структура точки в 3D
  9. struct Vec3 {
  10.     double x, y, z;
  11.  
  12.     Vec3() {
  13.         x = 0, y = 0, z = 0;
  14.     }
  15.     Vec3(double x, double y, double z) {
  16.         this->x = x;
  17.         this->y = y;
  18.         this->z = z;
  19.     }
  20.  
  21.     double get_distance(const Vec3* p2);
  22.     void print(int SetW = 4, int SetPrecision = 2);
  23. };
  24. // Получение расстояния между двумя точками
  25. double Vec3::get_distance(const Vec3* p2) {
  26.     return sqrt(pow(this->x - p2->x, 2) + pow(this->y - p2->y, 2) + pow(this->z - p2->z, 2));
  27. }
  28. // Вывод координат точки в консоль
  29. void Vec3::print(int SetW, int SetPrecision) {
  30.     cout << setw(SetW) << setprecision(SetPrecision) << this->x << " ";
  31.     cout << setw(SetW) << setprecision(SetPrecision) << this->y << " ";
  32.     cout << setw(SetW) << setprecision(SetPrecision) << this->z << endl;
  33. }
  34.  
  35.  
  36.  
  37. // Структура треугольника (содержит: 3 точки и свой периметр)
  38. struct Triangle {
  39.     Vec3* v1, * v2, * v3;
  40.     double perimeter;
  41.  
  42.     void update_perimeter();
  43.  
  44.     Triangle() {
  45.         v1 = NULL; v2 = NULL; v3 = NULL;
  46.         perimeter = -DBL_MAX; // Самое малое double
  47.     }
  48.     Triangle(Vec3* p1, Vec3* p2, Vec3* p3) {
  49.         v1 = p1; v2 = p2; v3 = p3;
  50.         update_perimeter();
  51.     }
  52.  
  53.     void print(int SetW = 4, int SetPrecision = 2);
  54. };
  55. // Функция для обновления периметра, при изменении точек (ручной вызов)
  56. void Triangle::update_perimeter() {
  57.     this->perimeter = v1->get_distance(v2) + v2->get_distance(v3) + v3->get_distance(v1);
  58. }
  59. // Вывод координат всех точек треугольника
  60. void Triangle::print(int SetW, int SetPrecision) {
  61.     cout << endl;
  62.     this->v1->print(SetW, SetPrecision);
  63.     this->v2->print(SetW, SetPrecision);
  64.     this->v3->print(SetW, SetPrecision);
  65. }
  66.  
  67.  
  68.  
  69. // Функция для получения случайного double в диапазоне
  70. double fRand(double fMin, double fMax)
  71. {
  72.     double f = (double)rand() / RAND_MAX;
  73.     return fMin + f * (fMax - fMin);
  74. }
  75. // Функция для удобного создания файла с <pcount> кол-вом точек со случайными координатами
  76. void createRandPoints(long pcount = 3, double dMin = -100.0, double dMax = 100.0) {
  77.     ofstream out("points.txt");
  78.  
  79.     if (pcount < 3)
  80.         pcount = 3;
  81.  
  82.     out << pcount << endl;
  83.     for (int i = 0; i < pcount; i++)
  84.         out << fRand(dMin, dMax) << " " << fRand(dMin, dMax) << " " << fRand(dMin, dMax) << endl;
  85.  
  86.     out.close();
  87. }
  88.  
  89. // Реализация "сочетания" C(m,n)
  90. long long unsigned int Combination(const int m, const int n) {
  91.     long long unsigned int fn = 1, dn = 1;
  92.     const int nm = n - m;
  93.     for (int i = 1; i <= n; i++) {
  94.         if (i <= m)
  95.             dn *= i;
  96.         if (i > nm)
  97.             fn *= i;
  98.  
  99.         if (fn % dn == 0) {
  100.             fn /= dn;
  101.             dn = 1;
  102.         }
  103.     }
  104.     return fn / dn;
  105. }
  106. // Главная ф-ция
  107. int main() {
  108.     long pointCount; string temp;
  109.  
  110.     // createRandPoints(1000);
  111.  
  112.     ifstream in("points.txt");
  113.     if (!in) return 0; // Файл пуст
  114.  
  115.     in >> temp;
  116.     pointCount = stoi(temp);
  117.  
  118.     // Основной массив, хранящий точки
  119.     Vec3* points = new Vec3[pointCount];
  120.  
  121.     // Заполнение массива из файла
  122.     for (Vec3* p = points; p < points + pointCount; p++) {
  123.         in >> temp;
  124.         p->x = stod(temp);
  125.         in >> temp;
  126.         p->y = stod(temp);
  127.         in >> temp;
  128.         p->z = stod(temp);
  129.     }
  130.     in.close();
  131.  
  132.     // Временный треугольник
  133.     auto t = new Triangle(new Vec3(), new Vec3(), new Vec3());
  134.  
  135.     // Треугольник с минимальным периметром
  136.     Triangle minTris = Triangle();
  137.     // Ставим ему максимальное возможное значение периметра (т.к. по стандарту оно минимально)
  138.     minTris.perimeter = -minTris.perimeter;
  139.  
  140.     /*
  141.         Реализация системы загрузки в процентах (pointCount < 4010)
  142.     */
  143.     // Счётчик кол-ва треугольников
  144.     long long unsigned int q = 0;
  145.     // Кол-во треугольников
  146.     const long long unsigned int trisCount = Combination(3, pointCount);
  147.     // Условие включения загрузки
  148.     const bool enableLoading = trisCount > 10000000;
  149.     // Деление процентов (прим 5%, 10%, 15%)
  150.     const int showByPrecents = 5;
  151.     // Количество треугольников для вывода процентов в консоль
  152.     const long long unsigned int onePrecentPiece = trisCount / (100 / showByPrecents);
  153.     // Счётчик процентов
  154.     int precent = 0;
  155.     /*
  156.         Самая эффективная реализация перебора всех сочетаний точек
  157.         в порядке возрастания адреса (чтение из массива)
  158.         не допускающая попадание одинаковых точек в один треугольник
  159.     */
  160.     for (auto p1 = points; p1 < points + (pointCount - 2); p1++) {
  161.         t->v1 = p1;
  162.         for (auto p2 = p1 + 1; p2 < points + (pointCount - 1); p2++) {
  163.             t->v2 = p2;
  164.             for (auto p3 = p2 + 1; p3 < points + (pointCount); p3++) {
  165.                 t->v3 = p3;
  166.                 q++;
  167.  
  168.                 // Сравнение периметров временного и минимального
  169.                 t->update_perimeter();
  170.                 if (minTris.perimeter > t->perimeter)
  171.                     minTris = *t;
  172.  
  173.                 // Реализация "загрузки"
  174.                 if (enableLoading)
  175.                     if (q % onePrecentPiece == 0) {
  176.                         precent += showByPrecents;
  177.                         cout << precent << " %" << endl;
  178.                     }
  179.                 /*  Раздельный if используется для экономии расчётов,
  180.                     т.к. если загрузка не нужна, то будет лишним проводить
  181.                     деление с остатком и его последуещее сравнение
  182.                 */
  183.             }
  184.         }
  185.     }
  186.     // Вывод результата
  187.     cout << "Tris count: " << q << endl;
  188.     cout << "Min perimiter: " << minTris.perimeter << endl;
  189.     cout << "Of triangle: ";
  190.     minTris.print(5, 3);
  191.  
  192.     return 0;
  193. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement