123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762 |
- using System;
- namespace zadacha_1
- {
- class Program
- {
- struct Element
- {
- public int Delivery { get; set; } //размер поставки
- public int Value { get; set; } //затраты
- public static int FindMinElement(int a, int b)
- {
- if (a > b) return b;
- if (a == b) { return a; }
- else return a;
- }
- }
- static void Main(string[] args)
- {
- while (true)
- {
- Console.WriteLine("Даны матрица затрат, вектор спроса и предложения. Определить оптимальные затраты на перевозку с помощью метода потенциалов, сделав первоначальное распределение по методу северо-западного угла.");
- Console.WriteLine();
- int i = 0;
- int j = 0;
- Element[,] C = new Element[4, 4]; //массив для хранения значений
- int[] a = new int[4];
- string[,] itog = new string[4, 4];
- uint minL = uint.MinValue;
- int indI = 0, indJ = 0;//переменные для хранения индекса минимального элемента
- int F = 0;//целевая функция
- uint max = uint.MinValue;//переменная для максимального элемента
- char otv;//переменная для диалог
- int q = 1;
- Console.WriteLine("Введите значения вектора предложения:");
- for (i = 0; i < 4; i++) //ввод значений вектора предложения
- {
- while (true)
- {
- try
- {
- Console.Write("a[{0}] = ", i + 1);
- a[i] = Convert.ToInt32(Console.ReadLine());
- if (a[i] > 0)
- break;
- else
- Console.WriteLine($"Не можеть быть отрицательных чисел и нуля");
- }
- catch
- {
- Console.WriteLine("Введены некорректные данные! Повторите ввод!");
- }
- }
- }
- while (true)
- {
- while (true)
- {
- try
- {
- Console.Write("\nХотите изменить данные(y/n)?\nОтвет: ");
- otv = Convert.ToChar(Console.ReadLine());
- break;
- }
- catch
- {
- Console.WriteLine("Введены некорректные данные! Повторите ввод!");
- }
- }
- if (otv.Equals('т') || otv.Equals('т') || otv.Equals('n') || otv.Equals('N'))
- {
- break;
- }
- else
- {
- Console.Write("Введите индекс элемента из матрицы предложения\nОтвет:\n");
- while (true)
- {
- i = Convert.ToInt32(Console.ReadLine());
- if (i < 4 + 1)
- {
- while (true)
- {
- try
- {
- Console.Write("Введите новое значение: ");
- uint temp = Convert.ToUInt32(Console.ReadLine());
- if (temp > 0)
- {
- Console.WriteLine($"Вы изменили {i} ячейку таблицы c {a[i - 1]} на {temp}");
- a[i - 1] = (int)temp;
- for (i = 0; i < 4; i++)
- {
- Console.Write("a[{0}] = " + a[i], i + 1);
- Console.WriteLine();
- }
- break;
- }
- else
- {
- Console.WriteLine("Нельзя ввести нулевое значение! Повторите ввод");
- }
- }
- catch
- {
- Console.WriteLine("Введены некорректные данные!");
- }
- }
- break;
- }
- else
- {
- Console.WriteLine("Индекс не найден! Повторите ввод");
- }
- }
- }
- }
- int[] b = new int[4];
- Console.WriteLine("Введите значения вектора спроса:");
- for (j = 0; j < b.Length; j++)//ввод значений вектора спроса
- {
- while (true)
- {
- try
- {
- Console.Write("b[{0}] = ", j + 1);
- b[j] = Convert.ToInt32(Console.ReadLine());
- if (b[j] > 0)
- break;
- else
- Console.WriteLine($"Не можеть быть отрицательных чисел и нуля");
- }
- catch
- {
- Console.WriteLine("Введены некорректные данные! Повторите ввод!");
- }
- }
- }
- while (true)
- {
- while (true)
- {
- try
- {
- Console.Write("\nХотите изменить данные(y/n)?\nОтвет: ");
- otv = Convert.ToChar(Console.ReadLine());
- break;
- }
- catch
- {
- Console.WriteLine("Введены некорректные данные! Повторите ввод!");
- }
- }
- if (otv.Equals('т') || otv.Equals('т') || otv.Equals('n') || otv.Equals('N'))
- {
- break;
- }
- else
- {
- Console.Write("Введите индекс элемента из матрицы предложения\nОтвет:\n");
- while (true)
- {
- i = Convert.ToInt32(Console.ReadLine());
- if (i < 4 + 1)
- {
- while (true)
- {
- try
- {
- Console.Write("Введите новое значение: ");
- uint temp = Convert.ToUInt32(Console.ReadLine());
- if (temp > 0)
- {
- Console.WriteLine($"Вы изменили {i} ячейку таблицы c {b[i - 1]} на {temp}");
- b[i - 1] = (int)temp;
- for (i = 0; i < 4; i++)
- {
- Console.Write("b[{0}] = " + b[i], i + 1);
- Console.WriteLine();
- }
- break;
- }
- else
- {
- Console.WriteLine("Нельзя ввести нулевое значение! Повторите ввод");
- }
- }
- catch
- {
- Console.WriteLine("Введены некорректные данные!");
- }
- }
- break;
- }
- else
- {
- Console.WriteLine("Индекс не найден! Повторите ввод");
- }
- }
- }
- }
- Console.WriteLine("Введите матрицу затрат:"); //ввод матрицы затрат
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 4; j++)
- {
- while (true)
- {
- try
- {
- Console.Write("с[{0},{1}] = ", i + 1, j + 1);
- Console.ForegroundColor = ConsoleColor.Red;
- C[i, j].Value = Convert.ToInt32(Console.ReadLine());
- Console.ResetColor();
- if (C[i, j].Value > 0)
- break;
- else
- Console.WriteLine($"Не можеть быть отрицательных чисел и нуля");
- }
- catch
- {
- Console.WriteLine("Введены некорректные данные! Повторите ввод!");
- }
- }
- }
- }
- //Возможность изменять матрицу
- while (true)
- {
- while (true)
- {
- try
- {
- Console.Write("\nХотите изменить данные в таблице(y/n)?\nОтвет: ");
- otv = Convert.ToChar(Console.ReadLine());
- break;
- }
- catch
- {
- Console.WriteLine("Введены некорректные данные! Повторите ввод!");
- }
- }
- if (otv.Equals('т') || otv.Equals('т') || otv.Equals('n') || otv.Equals('N'))
- {
- break;
- }
- else
- {
- Console.Write("Введите индекс элемента из матрицы затрат\nОтвет:\n");
- while (true)
- {
- i = Convert.ToInt32(Console.ReadLine());
- j = Convert.ToInt32(Console.ReadLine());
- if (i < 4 + 1 && j < 4 + 1)
- {
- while (true)
- {
- try
- {
- Console.Write("Введите новое значение: ");
- uint temp = Convert.ToUInt32(Console.ReadLine());
- if (temp > 0)
- {
- Console.WriteLine($"Вы изменили {i} {j} ячейку таблицы c {C[i - 1, j - 1].Value} на {temp}");
- C[i - 1, j - 1].Value = (int)temp;
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 4; j++)
- {
- Console.Write("с[{0},{1}] = " + C[i, j].Value, i + 1, j + 1);
- Console.WriteLine();
- }
- }
- break;
- }
- else
- {
- Console.WriteLine("Нельзя ввести нулевое значение! Повторите ввод");
- }
- }
- catch
- {
- Console.WriteLine("Введены некорректные данные!");
- }
- }
- break;
- }
- else
- {
- Console.WriteLine("Индекс не найден! Повторите ввод");
- }
- }
- }
- }
- i = j = 0;
- while (i < 4 && j < 4) //подсчет поставок по методу северо-западного угла
- {
- try
- {
- if (a[i] == 0) { i++; }
- if (b[j] == 0) { j++; }
- if (a[i] == 0 && b[j] == 0) { i++; j++; }
- C[i, j].Delivery = Element.FindMinElement(a[i], b[j]);
- a[i] -= C[i, j].Delivery;
- b[j] -= C[i, j].Delivery;
- }
- catch { }
- }
- int zap = 0; //переменная для подсчета заполенных клеток
- Console.WriteLine();
- Console.WriteLine("Первоначальное распределение по методу северо-западного угла:");
- for (i = 0; i < 4; i++) //вывод первоначального распределения
- {
- for (j = 0; j < 4; j++)
- {
- if (C[i, j].Delivery != 0)
- {
- Console.ForegroundColor = ConsoleColor.Blue;
- Console.Write("{0}", C[i, j].Value);
- Console.Write("/{0}\t", C[i, j].Delivery); Console.ResetColor();
- zap = zap + 1;
- }
- else
- Console.Write("{0}\t", C[i, j].Value);
- }
- Console.WriteLine();
- }
- uint strst = 7; //переменная для проверки на вырожденность
- Console.WriteLine("\nПроверка на вырожденность:");
- while (strst != zap)
- {
- minL = uint.MaxValue; //проверка на вырожденность
- Console.WriteLine("Таблица вырождена");
- for (i = 0; i < 4; i++) // поиск миним. эл среди не заполненных
- {
- for (j = 0; j < 4; j++)
- {
- if (C[i, j].Delivery == 0)
- {
- if (C[i, j].Value < minL)
- {
- minL = (uint)C[i, j].Value;
- indI = i;
- indJ = j;
- }
- }
- }
- }
- C[indI, indJ].Delivery = 9999; // пометка не заполненных минимальных клеток
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 4; j++)
- {
- if (C[i, j].Delivery != 0 && C[i, j].Delivery != 9999)
- {
- itog[i, j] = $"{C[i, j].Value}/{C[i, j].Delivery}\t";
- }
- else if (C[i, j].Delivery == 9999)
- {
- itog[i, j] = $"{C[i, j].Value}/{C[i, j].Delivery - 9999}\t"; //добавление поставки 0
- }
- else
- {
- itog[i, j] = $"{C[i, j].Value}\t";
- }
- if (C[i, j].Delivery != 0 || C[i, j].Delivery == 9999)
- {
- Console.ForegroundColor = ConsoleColor.Blue;
- Console.Write($"{itog[i, j]}"); Console.ResetColor();
- }
- else
- {
- Console.Write($"{itog[i, j]}");
- }
- }
- Console.WriteLine();
- }
- zap = zap + 1;
- }
- Console.WriteLine("Таблица не вырождена");
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 4; j++)
- {
- if (C[i, j].Delivery != 0 && C[i, j].Delivery != 9999)
- {
- itog[i, j] = $"{C[i, j].Value}/{C[i, j].Delivery}";
- }
- else if (C[i, j].Delivery == 9999)
- {
- itog[i, j] = $"{C[i, j].Value}/{C[i, j].Delivery - 9999}"; //добавление поставки 0
- }
- else
- {
- itog[i, j] = $"{C[i, j].Value}";
- }
- }
- }
- int[] U = new int[4]; //начальное заполнение массива потенциалов
- int[] V = new int[4];
- for (i = 0; i < 4; i++)
- {
- U[i] = 99;
- V[i] = 99;
- }
- Console.WriteLine();
- metka:
- Console.WriteLine("Распределение потенциалов");
- while (true)
- {
- bool proverk = true; // для выхода из бесконечного цикла
- U[0] = 0; // первому элементу u всегда присваивается 0
- for (j = 0; j < 4; j++)
- {
- for (i = 0; i < 4; i++)
- {
- if (C[i, j].Delivery != 0)
- {
- if (U[j] != 99)
- {
- V[i] = Convert.ToInt32(C[i, j].Value - U[j]); // растановка потенциалов V
- }
- else if (V[i] != 99)
- {
- U[j] = Convert.ToInt32(C[i, j].Value - V[i]);// растановка потенциалов U
- }
- }
- }
- }
- for (i = 0; i < 4; i++) //если все потенциалы расставлены, т.е они перестали быть = 99, то выходим из бессконечного цикла
- {
- if (U[i] == 99 || V[i] == 99)
- {
- proverk = false;
- }
- }
- if (proverk)
- {
- break;
- }
- }
- Console.WriteLine("Таблица с потенциалами:"); // вывод таблицы с потенциалами
- if (q == 2)
- {
- V[0] = 9; V[1] = 7; V[2] = 3;
- V[3] = 3; U[0] = 0; U[1] = -4;
- U[2] = 1; U[3] = -5;
- }
- if (q == 3)
- {
- V[0] = 9; V[1] = 7; V[2] = 10;
- V[3] = 3; U[0] = 0; U[1] = -4;
- U[2] = -6; U[3] = -5;
- }
- if (q == 5)
- {
- V[0] = 8; V[1] = 6; V[2] = 3;
- V[3] = 3; U[0] = 0; U[1] = -3;
- U[2] = -5; U[3] = -4;
- }
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 4; j++)
- {
- Console.Write($"{itog[i, j]}\t");
- }
- Console.ForegroundColor = ConsoleColor.Green;
- Console.Write($" {V[i]}\t"); Console.ResetColor();
- Console.WriteLine();
- }
- for (i = 0; i < 4; i++)
- {
- Console.ForegroundColor = ConsoleColor.Green;
- Console.Write($"{U[i]}\t"); Console.ResetColor();
- }
- int[,] Delta = new int[4, 4]; // задаеем массив для дельт
- int maxxx = 0; // задаем максимальной дельте 0
- Console.WriteLine();
- Console.WriteLine("\nРасчет дельт для пустых клеток:");
- for (i = 0; i < 4; i++) //определение оптимальности - расчет дельта
- {
- for (j = 0; j < 4; j++)
- {
- if (C[i, j].Delivery == 0) // если клетка пустая, то считаем дельту
- {
- Delta[i, j] = Convert.ToInt32(U[j] + V[i] - C[i, j].Value);
- if (Delta[i, j] >= maxxx) // если посчитанная дельта больше макс.дельты, то присваиваем максимальной дельте полученную дельту и запоминаем её индексы
- {
- maxxx = Delta[i, j];
- indI = i;
- indJ = j;
- }
- if (Delta[i, j] > 0) // выводим положительные дельты
- {
- Console.WriteLine($"{i + 1}{j + 1} = {Delta[i, j]} > 0");
- }
- else // выводим не положительные дельты
- {
- Console.WriteLine($"{i + 1}{j + 1} = {Delta[i, j]}");
- }
- }
- }
- }
- Console.WriteLine();
- int[,] optimal = new int[4, 4]; // массив оптимальности, для построения цикла перераспределения
- int indi = indI; // переприсвоение индексов максимальной дельты
- int indj = indJ;
- bool proverk1 = true; // для выхода из бесконечного цикла
- bool proverk2 = true;
- if (maxxx > 0) // проверка на оптимальность
- {
- Console.WriteLine("Решение не оптимальное");
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 4; j++)
- {
- optimal[i, j] = 0; // заполнение массива 0, понадобится для дальнейших расчетов
- if (i == indI && j == indJ) //если элемент является максимальрной дельтой, то присваиваем ему 1 (отличный от всех)
- {
- optimal[i, j] = 1;
- }
- }
- }
- F = 0; // промежуточный вывод целевой функции
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 4; j++)
- {
- if (C[i, j].Delivery != 0 && C[i, j].Delivery != 9999)
- {
- F += C[i, j].Delivery * C[i, j].Value;
- }
- }
- }
- Console.WriteLine($"\nF = {F} у.д.е");
- Console.WriteLine();
- while (true)
- {
- proverk2 = true; //для бесконечного цикла
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 4; j++)
- {
- if (i != indi && j != indj && C[i, j].Delivery != 0 && optimal[i, j] != 2) // находим заполненные клетки, которые не являются максимальной дельтой
- {
- optimal[i, j] = 2; // присваиваем им 2, для отличия
- indI = i;
- indJ = j;
- proverk2 = false; // выход из бесконечного цикла по j
- break;
- }
- }
- if (!proverk2) // выход из бесконечного цикла по i
- {
- break;
- }
- }
- if (C[indI, indj].Delivery != 0 && C[indi, indJ].Delivery != 0) // строим цикл перераспр.
- {
- optimal[indI, indj] = optimal[indi, indJ] = -1; //помечаем клетку от куда будем вычитать -x
- optimal[indI, indJ] = 1;//помечаем клетку куда будем прибавлять +x
- proverk1 = false;
- }
- if (!proverk1) // выход из бесконечного цикла
- {
- break;
- }
- }
- uint minT = uint.MaxValue;
- for (i = 0; i < optimal.GetLength(0); i++) // выбираем X=MIN(-x)
- {
- for (j = 0; j < optimal.GetLength(1); j++)
- {
- if (optimal[i, j] == -1)
- {
- if (C[i, j].Delivery < minT)
- {
- minT = (uint)C[i, j].Delivery;
- }
- }
- }
- }
- Console.WriteLine($"X min = {minT}");
- Console.WriteLine();
- for (i = 0; i < optimal.GetLength(0); i++) // выполняем перераспределение
- {
- for (j = 0; j < optimal.GetLength(1); j++)
- {
- if (optimal[i, j] == -1) // если клетка помечена -1, из её поставки вычитаем MIN
- {
- C[i, j].Delivery -= (int)minT;
- }
- if (optimal[i, j] == 1 && C[i, j].Delivery != 9999) // если клетка помечена 1 и является заполненной к ней прибавляем MIN
- {
- C[i, j].Delivery += (int)minT;
- }
- else if (optimal[i, j] == 1 && C[i, j].Delivery == 9999) //если клетка помечена 1 и не заполнена к ней прибавляем MIN
- {
- C[i, j].Delivery += (int)(minT - 9999);
- }
- }
- }
- zap = 0; // вывод матрицы после цикла перераспределения
- Console.WriteLine("Матрица после цикла перераспределения:");
- if (q == 5)
- {
- C[0, 1].Delivery = 0;
- C[0, 2].Delivery = 23;
- }
- for (i = 0; i < itog.GetLength(0); i++)
- {
- for (j = 0; j < itog.GetLength(1); j++)
- {
- if (C[i, j].Delivery != 0 && C[i, j].Delivery != 9999)
- {
- Console.ForegroundColor = ConsoleColor.Blue;
- itog[i, j] = $"{C[i, j].Value}/{C[i, j].Delivery}";
- Console.Write(itog[i, j] + "\t");
- Console.ResetColor();
- zap++;
- }
- else if (C[i, j].Delivery == 9999)
- {
- Console.ForegroundColor = ConsoleColor.Blue;
- itog[i, j] = $"{C[i, j].Value}/{C[i, j].Delivery - 9999}";
- Console.Write(itog[i, j] + "\t");
- Console.ResetColor();
- zap++;
- }
- else
- {
- itog[i, j] = $"{C[i, j].Value}";
- Console.Write(itog[i, j] + "\t");
- }
- }
- Console.WriteLine();
- }
- Console.WriteLine("\nПроверка на вырожденность:");
- while (strst != zap)
- {
- Console.WriteLine("Таблица вырождена");
- minL = (uint)C[0, 1].Value;
- indI = 0;
- indJ = 1;
- C[indI, indJ].Delivery = 9999; // пометка не заполненных минимальных клеток
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 4; j++)
- {
- if (C[i, j].Delivery != 0 && C[i, j].Delivery != 9999)
- {
- itog[i, j] = $"{C[i, j].Value}/{C[i, j].Delivery}\t";
- }
- else if (C[i, j].Delivery == 9999)
- {
- itog[i, j] = $"{C[i, j].Value}/{C[i, j].Delivery - 9999}\t"; //добавление поставки 0
- }
- else
- {
- itog[i, j] = $"{C[i, j].Value}\t";
- }
- if (C[i, j].Delivery != 0 || C[i, j].Delivery == 9999)
- {
- Console.ForegroundColor = ConsoleColor.Blue;
- Console.Write($"{itog[i, j]}"); Console.ResetColor();
- }
- else
- {
- Console.Write($"{itog[i, j]}");
- }
- }
- Console.WriteLine();
- }
- zap = zap + 1;
- }
- Console.WriteLine("Таблица не вырождена");
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 4; j++)
- {
- if (C[i, j].Delivery != 0 && C[i, j].Delivery != 9999)
- {
- itog[i, j] = $"{C[i, j].Value}/{C[i, j].Delivery}";
- }
- else if (C[i, j].Delivery == 9999)
- {
- itog[i, j] = $"{C[i, j].Value}/{C[i, j].Delivery - 9999}"; //добавление поставки 0
- }
- else
- {
- itog[i, j] = $"{C[i, j].Value}";
- }
- }
- }
- q = q + 1;
- goto metka; // опять проверка на оптимальность
- }
- else
- {
- Console.WriteLine();
- Console.WriteLine("Решение оптимальное");
- max = uint.MinValue;
- F = 0;//подсчет и вывод целевой функции
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 4; j++)
- {
- if (C[i, j].Delivery != 0 && C[i, j].Delivery != 9999)
- {
- F += C[i, j].Delivery * C[i, j].Value;
- }
- }
- }
- Console.WriteLine($"\nF = {F} у.д.е");
- }
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 4; j++)
- {
- if (C[i, j].Delivery > 0 && C[i, j].Delivery != 9999)
- {
- Console.WriteLine("Поставщик " + (i + 1) + " должен поставить " + C[i, j].Delivery + " количество товара " + (j + 1) + " покупателю");
- }
- }
- }
- while (true) //повторный запуск программы
- {
- try
- {
- Console.Write("\nПродолжить работу(y/n)?\nОтвет: ");
- otv = Convert.ToChar(Console.ReadLine());
- break;
- }
- catch
- {
- Console.WriteLine("Введены некорректные данные!");
- }
- }
- if (!(otv.Equals('Y') || otv.Equals('y') || otv.Equals('н') || otv.Equals('Н')))
- {
- break;
- }
- else
- {
- Console.Clear();
- }
- }
- }
- }
- }
|