Advertisement
DasShelmer

10.1.19+ point(int3)

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