Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <string>
- #include <fstream>
- #include <iomanip>
- #include <math.h>
- using namespace std;
- // Структура точки в 3D
- struct point {
- int x, y, z;
- };
- // Получение расстояния между двумя точками
- double get_distance(const point* p1, const point* p2) {
- return sqrt(pow(p1->x - p2->x, 2) + pow(p1->y - p2->y, 2) + pow(p1->z - p2->z, 2));
- }
- // Вывод координат точки в консоль
- void pPrint(const point* p) {
- cout << p->x << " ";
- cout << p->y << " ";
- cout << p->z << endl;
- }
- // Структура треугольника (содержит: 3 точки и свой периметр)
- struct Triangle {
- point* v1, * v2, * v3;
- double perimeter;
- void update_perimeter();
- Triangle() {
- v1 = NULL; v2 = NULL; v3 = NULL;
- perimeter = -DBL_MAX; // Самое малое double
- }
- Triangle(point* p1, point* p2, point* p3) {
- v1 = p1; v2 = p2; v3 = p3;
- update_perimeter();
- }
- void print(int SetW = 4, int SetPrecision = 2);
- };
- // Функция для обновления периметра, при изменении точек (ручной вызов)
- void Triangle::update_perimeter() {
- this->perimeter = get_distance(v1, v2) + get_distance(v2, v3) + get_distance(v3, v1);
- }
- // Вывод координат всех точек треугольника
- void Triangle::print() {
- cout << endl;
- pPrint(this->v1);
- pPrint(this->v2);
- pPrint(this->v3);
- }
- // Функция для получения случайного double в диапазоне
- int iRand(int iMin, int iMax) {
- int i = rand();
- return iMin + (float)i / RAND_MAX * (iMax - iMin);
- }
- // Функция для удобного создания файла с <pcount> кол-вом точек со случайными координатами
- void createRandPoints(long pcount = 3, int iMin = -100, int iMax = 100) {
- ofstream out("points.txt");
- if (pcount < 3)
- pcount = 3;
- out << pcount << endl;
- for (int i = 0; i < pcount; i++)
- out << iRand(iMin, iMax) << " " << iRand(iMin, iMax) << " " << iRand(iMin, iMax) << endl;
- out.close();
- }
- // Реализация "сочетания" C(m,n)
- long long unsigned int Combination(const int m, const int n) {
- long long unsigned int fn = 1, dn = 1;
- const int nm = n - m;
- for (int i = 1; i <= n; i++) {
- if (i <= m)
- dn *= i;
- if (i > nm)
- fn *= i;
- if (fn % dn == 0) {
- fn /= dn;
- dn = 1;
- }
- }
- return fn / dn;
- }
- // Главная ф-ция
- int main() {
- long pointCount; string temp;
- createRandPoints(1000);
- ifstream in("points.txt");
- if (!in) return 0; // Файл пуст
- in >> temp;
- pointCount = stoi(temp);
- // Основной массив, хранящий точки
- point* points = new point[pointCount];
- // Заполнение массива из файла
- for (point* p = points; p < points + pointCount; p++) {
- in >> temp;
- p->x = stoi(temp);
- in >> temp;
- p->y = stoi(temp);
- in >> temp;
- p->z = stoi(temp);
- }
- in.close();
- // Временный треугольник
- auto t = new Triangle(new point(), new point(), new point());
- // Треугольник с минимальным периметром
- Triangle minTris = Triangle();
- // Ставим ему максимальное возможное значение периметра (т.к. по стандарту оно минимально)
- minTris.perimeter = -minTris.perimeter;
- /*
- Реализация системы загрузки в процентах (pointCount < 4010)
- */
- // Счётчик кол-ва треугольников
- long long unsigned int q = 0;
- // Кол-во треугольников
- const long long unsigned int trisCount = Combination(3, pointCount);
- // Условие включения загрузки
- const bool enableLoading = trisCount > 10000000;
- // Деление процентов (прим 5%, 10%, 15%)
- const int showByPrecents = 5;
- // Количество треугольников для вывода процентов в консоль
- const long long unsigned int onePrecentPiece = trisCount / (100 / showByPrecents);
- // Счётчик процентов
- int precent = 0;
- /*
- Самая эффективная реализация перебора всех сочетаний точек
- в порядке возрастания адреса (чтение из массива)
- не допускающая попадание одинаковых точек в один треугольник
- */
- for (auto p1 = points; p1 < points + (pointCount - 2); p1++) {
- t->v1 = p1;
- for (auto p2 = p1 + 1; p2 < points + (pointCount - 1); p2++) {
- t->v2 = p2;
- for (auto p3 = p2 + 1; p3 < points + (pointCount); p3++) {
- t->v3 = p3;
- q++;
- // Сравнение периметров временного и минимального
- t->update_perimeter();
- if (minTris.perimeter > t->perimeter)
- minTris = *t;
- // Реализация "загрузки"
- if (enableLoading)
- if (q % onePrecentPiece == 0) {
- precent += showByPrecents;
- cout << precent << " %" << endl;
- }
- /* Раздельный if используется для экономии расчётов,
- т.к. если загрузка не нужна, то будет лишним проводить
- деление с остатком и его последуещее сравнение
- */
- }
- }
- }
- // Вывод результата
- cout << "Tris count: " << q << endl;
- cout << "Min perimiter: " << minTris.perimeter << endl;
- cout << "Of triangle: ";
- minTris.print();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement