123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664 |
- using System;
- namespace matmodelirovanie
- {
- class program
- {
- static void Main(string[] args)
- {
- while (true)
- {
- Console.WriteLine("Задача №3.\nНахождение оптимального распределения трех видов механизмов между тремя участками работ. ");//постановка задачи
- uint r1, r2;//размерности матрицы и векторов
- r1 = 3;
- r2 = 3;
- char otv;//переменная для диалога
- uint[,] arr = new uint[r2, r1];//матрица затрат
- uint[] m = new uint[r2];//вектор мощности
- uint[] n = new uint[r1];//вектор спроса
- uint valueM = 0, valueN = 0;//переменные для подсчета суммы
- uint min = uint.MaxValue;//переменная для поиска минимального элемента
- uint max = uint.MinValue;//переменная для поиска максимального элемента
- uint minL = uint.MinValue;
- uint maxx = uint.MinValue;//переменная для поиска максимального элемента
- int indI = 0, indJ = 0;//переменные для хранения индекса минимального элемента
- int indII = 0, indJJ = 0;//переменные для хранения индекса максимального элемента
- uint[,] raspr = new uint[r2, r1];//массив в котором хранятся значения, куда и сколько использовалось механизмов
- uint F = 0;//целевая функция
- string[] postavki = new string[0];//массив строк в котором прописано, кто с кем заключил договор
- string[,] itog = new string[r2, r1];//матрица, которая схожа с исходной, но в ней проставлены поставки через слеш
- Console.WriteLine();
- Console.WriteLine("Ввод данных об эффективности использования механизмов конкретного типа на участках работы:");
- for (int i = 0; i < arr.GetLength(0); i++)
- {
- for (int j = 0; j < arr.GetLength(1); j++)
- {
- while (true) // ввод данных об эффективности использования механизмов конкретного типа на участках работы
- {
- try
- {
- Console.Write($"Введите производительность {i + 1}-го механизма при работе на {j + 1}-ом участке: ");
- arr[i, j] = Convert.ToUInt32(Console.ReadLine());
- if (arr[i, j] > 0)
- break;
- else
- {
- Console.WriteLine($"Не можеть быть 0");
- }
- }
- catch
- {
- Console.WriteLine("Введены некорректные данные!");
- }
- }
- }
- }
- while (true) // ввод данных об количестве механизмов каждого типа
- {
- Console.WriteLine();
- Console.WriteLine("Ввод данных о количестве механизмов каждого типа:");
- for (int i = 0; i < m.Length; i++)
- {
- while (true)
- {
- try
- {
- Console.Write($"Введите количество механизмов {i + 1}-го типа: ");
- m[i] = Convert.ToUInt32(Console.ReadLine());
- break;
- }
- catch
- {
- Console.WriteLine("Введены некорректные данные!");
- }
- }
- }
- Console.WriteLine();
- Console.WriteLine("Ввод данных о запрашиваемых механизмах для каждого участка:");
- for (int i = 0; i < n.Length; i++)
- {
- while (true) //ввод данных о запрашиваемых механизмах для каждого участка
- {
- try
- {
- Console.Write($"Введите количество запрашиваемых механизмов для {i + 1}-го участка работы: ");
- n[i] = Convert.ToUInt32(Console.ReadLine());
- break;
- }
- catch
- {
- Console.WriteLine("Введены некорректные данные!");
- }
- }
- }
- for (int i = 0; i < m.Length; i++) // проверка на одинаковость суммы векторов
- {
- valueM += m[i];
- }
- for (int i = 0; i < n.Length; i++)
- {
- valueN += n[i];
- }
- if (valueM == valueN)
- {
- break;
- }
- else
- {
- Console.WriteLine("Вектор механизмов и участков работ должны быть равны, повторите ввод!");
- valueM = 0;
- valueN = 0;
- }
- }
- Console.WriteLine();
- //вывод таблицы производительности и векторов
- Console.WriteLine("\nТаблица производительности:");
- for (int i = 0; i < arr.GetLength(0); i++)
- {
- for (int j = 0; j < arr.GetLength(1); j++)
- {
- Console.Write($"{arr[i, j]} ");
- }
- Console.WriteLine();
- }
- Console.WriteLine();
- Console.WriteLine("Вектор механизмов (m):");
- for (int i = 0; i < m.Length; i++)
- {
- Console.Write($"{m[i]} ");
- }
- Console.WriteLine();
- Console.WriteLine("\nВектор участков работы (n):");
- for (int i = 0; i < n.Length; i++)
- {
- Console.Write($"{n[i]} ");
- }
- //Возможность изменять матрицу
- while (true)
- {
- while (true)
- {
- try
- {
- Console.Write("\nХотите изменить данные в таблице?\nЕсли нет, то нажмите на кнопку Д на клавиатуре\nЕсли да, то можете нажать на любую другую кнопку\nОтвет: ");
- otv = Convert.ToChar(Console.ReadLine());
- break;
- }
- catch
- {
- Console.WriteLine("Введены некорректные данные!");
- }
- }
- if (otv.Equals('l') || otv.Equals('д') || otv.Equals('Д') || otv.Equals('L'))
- {
- break;
- }
- else
- {
- Console.Write("Введите номер вида механизма, затем номер участка работ, который вы хотите изменить\nОтвет:\n");
- while (true)
- {
- int i = Convert.ToInt32(Console.ReadLine()), j = Convert.ToInt32(Console.ReadLine());
- if (i < r2 + 1 && j < r1 + 1)
- {
- while (true)
- {
- try
- {
- Console.Write("Введите новое значение: ");
- uint temp = Convert.ToUInt32(Console.ReadLine());
- if (temp != 0)
- {
- Console.WriteLine($"Вы изменили {i} {j} ячейку таблицы c {arr[i - 1, j - 1]} на {temp}");
- arr[i - 1, j - 1] = temp;
- break;
- }
- else
- {
- Console.WriteLine("Нельзя ввести нулевое значение! Повторите ввод");
- }
- }
- catch
- {
- Console.WriteLine("Введены некорректные данные!");
- }
- }
- break;
- }
- else
- {
- Console.WriteLine("Введенная размерность не соответствует! Повторите ввод");
- }
- }
- }
- }
- Console.Clear();
- Console.WriteLine("\nМатрица:"); //вывод матрицы тарифов
- Console.Write(" ");
- for (int i = 0; i < n.Length; i++)
- {
- Console.Write($"{n[i]} ");
- }
- Console.WriteLine();
- for (int i = 0; i < arr.GetLength(0); i++)
- {
- Console.Write($"{m[i]} ");
- for (int j = 0; j < arr.GetLength(1); j++)
- {
- Console.Write($"{arr[i, j]} ");
- }
- Console.WriteLine();
- }
- for (int i = 0; i < raspr.GetLength(0); i++) // создание таблицы распределения и заполнение её пока что нулями
- {
- for (int j = 0; j < raspr.GetLength(1); j++)
- {
- raspr[i, j] = 0;
- }
- }
- max = uint.MinValue; // Максимальное значение
- for (int i = 0; i < arr.GetLength(0); i++) // поиск максимального и преобразование по формуле Maxl+1-A
- {
- for (int j = 0; j < arr.GetLength(1); j++)
- {
- if (arr[i, j] > max)
- {
- max = arr[i, j];
- }
- }
- }
- max = max + 1;
- for (int i = 0; i < arr.GetLength(0); i++)
- {
- for (int j = 0; j < arr.GetLength(1); j++)
- {
- arr[i, j] = max - arr[i, j]; // преобразование по формуле Maxl+1-A
- }
- }
- Console.WriteLine("\nПреобразование значений матрицы:"); // вывод преобразованной таблицы
- for (int i = 0; i < arr.GetLength(0); i++)
- {
- for (int j = 0; j < arr.GetLength(1); j++)
- {
- Console.Write($" {arr[i, j]} ");
- }
- Console.WriteLine();
- }
- while (true) //алгоритм решения по минимальному элементу
- {
- min = uint.MaxValue;
- valueM = 0;
- valueN = 0;
- for (int i = 0; i < arr.GetLength(0); i++)
- {
- for (int j = 0; j < arr.GetLength(1); j++)
- {
- if (arr[i, j] < min && raspr[i, j] == 0 && m[i] != 0 && n[j] != 0)
- {
- min = arr[i, j];
- indI = i;
- indJ = j;
- }
- }
- }
- if (n[indJ] != 0 && m[indI] != 0)
- {
- if (n[indJ] > m[indI])
- {
- raspr[indI, indJ] = m[indI];
- n[indJ] -= m[indI];
- m[indI] = 0;
- }
- else
- {
- raspr[indI, indJ] = n[indJ];
- m[indI] -= n[indJ];
- n[indJ] = 0;
- }
- }
- for (int i = 0; i < m.Length; i++) // проверка на то, что первоначальное рапределение выполнено полностью
- {
- valueM += m[i];
- }
- for (int i = 0; i < n.Length; i++)
- {
- valueN += n[i];
- }
- if (valueM == 0 && valueN == 0)
- {
- break;
- }
- }
- Console.WriteLine("\nПервоначальное распределение методом минимального элемента:");
- uint zap = 0;//переменная для подсчета заполненных клеток, понадобиться для проверки вырожденности
- for (int i = 0; i < itog.GetLength(0); i++) //вывод матрицы, в которой через слеш написаны поставки
- {
- for (int j = 0; j < itog.GetLength(1); j++)
- {
- if (raspr[i, j] != 0)
- {
- itog[i, j] = $"{arr[i, j]}/{raspr[i, j]}";
- zap = zap + 1;
- }
- else
- {
- itog[i, j] = $"{arr[i, j]} ";
- }
- Console.Write($"{itog[i, j]} ");
- }
- Console.WriteLine();
- }
- uint strst = r1 + r2 - 1;
- minL = uint.MaxValue; //проверка на вырожденность
- Console.WriteLine();
- Console.WriteLine("\nПроверка на вырожденность:");
- if (strst != zap) //если количество заполненных клеток не равно столбцы+строки-1, то приписание 0 в мин поставку из свободных
- {
- Console.WriteLine("Таблица вырождена");
- for (int i =
- 0; i < arr.GetLength(0); i++) // поиск миним. эл среди не заполненных
- {
- for (int j = 0; j < arr.GetLength(1); j++)
- {
- if (raspr[i, j] == 0)
- {
- if (arr[i, j] < minL)
- {
- minL = arr[i, j];
- indI = i;
- indJ = j;
- }
- }
- }
- }
- raspr[indI, indJ] = 9999; // помечаем не заполненные минимальные клетки
- for (int i = 0; i < itog.GetLength(0); i++)
- {
- for (int j = 0; j < itog.GetLength(1); j++)
- {
- if (raspr[i, j] != 0 && raspr[i, j] != 9999)
- {
- itog[i, j] = $"{arr[i, j]}/{raspr[i, j]}";
- }
- else if (raspr[i, j] == 9999)
- {
- itog[i, j] = $"{arr[i, j]}/{raspr[i, j] - 9999}"; //добавление поставки 0
- }
- else
- {
- itog[i, j] = $"{arr[i, j]} ";
- }
- Console.Write($"{itog[i, j]} ");
- }
- Console.WriteLine();
- }
- }
- else
- {
- Console.WriteLine("Таблица не вырождена");
- }
- metka:
- Console.WriteLine();
- int[] U = new int[r2]; // начальное заполнение массива потенциалов, для дальнейшего решения
- int[] V = new int[r1];
- for (int i = 0; i < r1; i++)
- {
- U[i] = 99;
- V[i] = 99;
- }
- //Для заполненных клеток рассчитываются потенциалы Uj и Vi
- // проверка на то, является ли ячейка пустой и не записаны ли для неё потенциалы, если нет, то высчитывается потенциал
- Console.WriteLine("Расчёт потенциалов");
- while (true)
- {
- bool proverk = true; // для выхода из бесконечного цикла
- U[0] = 0; // первому элементу u всегда присваивается 0
- for (int j = 0; j < r2; j++)
- {
- for (int i = 0; i < r1; i++)
- {
- if (raspr[i, j] != 0)
- {
- if (U[j] != 99)
- {
- V[i] = Convert.ToInt32(arr[i, j] - U[j]); // растановка потенциалов V
- }
- else if (V[i] != 99)
- {
- U[j] = Convert.ToInt32(arr[i, j] - V[i]);// растановка потенциалов U
- }
- }
- }
- }
- for (int i = 0; i < r1; i++) // если все потенциалы расставлены, т.е они перестали быть = 99, то выходим из бессконечного цикла
- {
- if (U[i] == 99 || V[i] == 99)
- {
- proverk = false;
- }
- }
- if (proverk)
- {
- break;
- }
- }
- Console.WriteLine("Таблица с раставленными потенциалами:"); // вывод таблицы с потенциалами
- for (int i = 0; i < arr.GetLength(0); i++)
- {
- for (int j = 0; j < arr.GetLength(1); j++)
- {
- Console.Write($"{itog[i, j]} ");
- }
- Console.Write($" {V[i]}");
- Console.WriteLine();
- }
- for (int i = 0; i < arr.GetLength(1); i++)
- {
- Console.Write($"{U[i]} ");
- }
- Console.WriteLine();
- Console.WriteLine();
- int[,] Delta = new int[r2, r1]; // задаеем массив дельт
- int maxxx = 0; // задаем максимпальной дельте 0
- Console.WriteLine("Для пустых клеток расчет дельты:");
- for (int i = 0; i < arr.GetLength(0); i++) //определение оптимальности - расчет дельта
- {
- for (int j = 0; j < arr.GetLength(1); j++)
- {
- if (raspr[i, j] == 0) // если клетка пустая, то считаем дельту
- {
- Delta[i, j] = Convert.ToInt32(U[j] + V[i] - arr[i, j]);
- if (Delta[i, j] > maxxx) // если посчитанная дельта больше макс.дельты, то присваиваем максимальной дельте полученную дельту и запоминаем её индексы
- {
- maxxx = Delta[i, j];
- indI = i;
- indJ = j;
- }
- if (Delta[i, j] == maxxx && Delta[i, j] != 0) // выводим положительные дельты
- {
- Console.WriteLine($"{i + 1}{j + 1} = {Delta[i, j]} - max");
- }
- else // выводим не положительные дельты
- {
- Console.WriteLine($"{i + 1}{j + 1} = {Delta[i, j]}");
- }
- }
- }
- }
- Console.WriteLine();
- int[,] optimal = new int[r2, r1]; // массив оптимальности, для построения цикла перераспределения
- int indi = indI; // переприсвоение индексов максимальной дельты
- int indj = indJ;
- bool proverk1 = true; // для выхода из бесконечного цикла
- bool proverk2 = true;
- if (maxxx > 0) // проверка на оптимальность
- {
- Console.WriteLine("Решение не оптимальное:");
- for (int i = 0; i < optimal.GetLength(0); i++)
- {
- for (int j = 0; j < optimal.GetLength(0); j++)
- {
- optimal[i, j] = 0; // заполнение массива 0, понадобится для дальнейших расчетов
- if (i == indI && j == indJ) //если элемент является максимальрной дельтой, то присваиваем ему 1 (отличный от всех)
- {
- optimal[i, j] = 1;
- }
- }
- }
- F = 0; // промежуточный вывод целувой функции
- for (int i = 0; i < raspr.GetLength(0); i++)
- {
- for (int
- j = 0; j < raspr.GetLength(1); j++)
- {
- if (raspr[i, j] != 0 && raspr[i, j] != 9999)
- {
- F += raspr[i, j] * arr[i, j];
- }
- }
- }
- Console.WriteLine($"\nF = {F} у.д.е");
- Console.WriteLine();
- while (true)
- {
- proverk2 = true; //для бесконечного цикла
- for (int i = 0; i < optimal.GetLength(0); i++)
- {
- for (int j = 0; j < optimal.GetLength(1); j++)
- {
- if (i != indi && j != indj && raspr[i, j] != 0 && optimal[i, j] != 2) // находим заполненные клетки, которые не являются максимальной дельтой
- {
- optimal[i, j] = 2; // присваиваем им 2, для отличия
- indI = i;
- indJ = j;
- proverk2 = false; // выход из бесконечного цикла по j
- break;
- }
- }
- if (!proverk2) // выход из бесконечного цикла по i
- {
- break;
- }
- }
- if (raspr[indI, indj] != 0 && raspr[indi, indJ] != 0) // строим цикл перераспр.
- {
- optimal[indI, indj] = optimal[indi, indJ] = -1; //помечаем клетку от куда будем вычитать -x
- optimal[indI, indJ] = 1;//помечаем клетку куда будем прибавлять +x
- proverk1 = false;
- }
- if (!proverk1) // выход из бесконечного цикла
- {
- break;
- }
- }
- uint minT = uint.MaxValue;
- for (int i = 0; i < optimal.GetLength(0); i++) // выбираем X=MIN(-x)
- {
- for (int j = 0; j < optimal.GetLength(1); j++)
- {
- if (optimal[i, j] == -1)
- {
- if (raspr[i, j] < minT)
- {
- minT = raspr[i, j];
- }
- }
- }
- }
- Console.WriteLine($"X = MIN = {minT}");
- Console.WriteLine();
- for (int i = 0; i < optimal.GetLength(0); i++) // выполняем перераспределение
- {
- for (int j = 0; j < optimal.GetLength(1); j++)
- {
- if (optimal[i, j] == -1) // если клетка помечена -1, из её поставки вычитаем MIN
- {
- raspr[i, j] -= Convert.ToUInt32(minT);
- }
- if (optimal[i, j] == 1 && raspr[i, j] != 9999) // если клетка помечена 1 и является заполненной к ней прибавляем MIN
- {
- raspr[i, j] += Convert.ToUInt32(minT);
- }
- else if (optimal[i, j] == 1 && raspr[i, j] == 999) //если клетка помечена 1 и не заполнена к ней прибавляем MIN
- {
- raspr[i, j] += Convert.ToUInt32(minT) - 999;
- }
- }
- }
- zap = 0; // вывод матрицы после цикла перераспределения
- Console.WriteLine("Построенные цикл перераспределения");
- for (int i = 0; i < itog.GetLength(0); i++)
- {
- for (int j = 0; j < itog.GetLength(1); j++)
- {
- if (raspr[i, j] != 0 && raspr[i, j] != 9999)
- {
- itog[i, j] = $"{arr[i, j]}/{raspr[i, j]} ";
- zap++;
- }
- else if (raspr[i, j] == 9999)
- {
- itog[i, j] = $"{arr[i, j]}/{raspr[i, j] - 9999} ";
- zap++;
- }
- else
- {
- itog[i, j] = $"{arr[i, j]} ";
- }
- Console.Write($"{itog[i, j]} ");
- }
- Console.WriteLine();
- }
- goto metka; // опять проверка на оптимальность
- }
- else
- {
- Console.WriteLine();
- Console.WriteLine("Решение оптимальное:");
- max = uint.MinValue; // Максимальное значение
- for (int i = 0; i < arr.GetLength(0); i++) // поиск максимального и преобразование по формуле Maxl+1-A
- {
- for (int j = 0; j < arr.GetLength(1); j++)
- {
- if (arr[i, j] > max)
- {
- max = arr[i, j];
- }
- }
- }
- max = max + 1;
- for (int i = 0; i < arr.GetLength(0); i++)
- {
- for (int j = 0; j < arr.GetLength(1); j++)
- {
- arr[i, j] = max - arr[i, j]; // преобразование по формуле Maxl+1-A
- }
- }
- Console.WriteLine("\nОбратное преобразование матрицы:"); // вывод преобразованной таблицы
- for (int i = 0; i < itog.GetLength(0); i++)
- {
- for (int j = 0; j < itog.GetLength(1); j++)
- {
- if (raspr[i, j] != 0 && raspr[i, j] != 9999)
- {
- itog[i, j] = $"{arr[i, j]}/{raspr[i, j]}";
- zap++;
- }
- else if (raspr[i, j] == 9999)
- {
- itog[i, j] = $"{arr[i, j]}/{raspr[i, j] - 9999}";
- zap++;
- }
- else
- {
- itog[i, j] = $"{arr[i, j]} ";
- }
- Console.Write($"{itog[i, j]} ");
- }
- Console.WriteLine();
- }
- F = 0;//подсчет и вывод целевой функции
- for (int i = 0; i < raspr.GetLength(0); i++)
- {
- for (int j = 0; j < raspr.GetLength(1); j++)
- {
- if (raspr[i, j] != 0 && raspr[i, j] != 9999)
- {
- F += raspr[i, j] * arr[i, j];
- }
- }
- }
- Console.WriteLine($"\nF = {F} у.д.е");
- }
- // повтор выполнения программы
- while (true)
- {
- try
- {
- Console.Write("\nХотите повторить выполнение программы?\nЕсли да, то нажмите на кнопку Y(на англ) на клавиатуре\nЕсли нет, то можете нажать на любую другую кнопку\nОтвет: ");
- otv = Convert.ToChar(Console.ReadLine());
- break;
- }
- catch
- {
- Console.WriteLine("Введены некорректные данные!");
- }
- }
- if (!(otv.Equals('Y') || otv.Equals('y') || otv.Equals('н') || otv.Equals('Н')))
- {
- Console.WriteLine("Программу выполнила студентка группы 31П\nЛебедева Александра Федоровна");
- break;
- }
- else
- {
- Console.Clear();
- }
- }
- }
- }
- }
|