123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Runtime.InteropServices;
- using System.Text;
- using System.Threading.Tasks;
- namespace MathModeling
- {
- internal class Program
- {
- static void Main(string[] args)
- {
- int[,] supplyAndDemand = { {16, 26, 12, 24, 3 },
- { 5, 2, 19, 27, 2 },
- { 29, 23, 25, 16, 8 },
- { 2, 25, 14, 15, 21 } };
- int[] consumers = { 14, 14, 14, 14 };
- int[] providers = { 13, 5, 13, 12, 13 };
- if (consumers.Sum() == providers.Sum())
- {
- PhogelMethod(supplyAndDemand, consumers, providers);
- PrintTable(supplyAndDemand);
- }
- else
- {
- Console.WriteLine("Некорректные данные!");
- }
- Console.ReadKey();
- }
- private static void MinElementMethod(int[,] supplyAndDemand, int[] consumers, int[] providers)
- {
- bool[,] fill = new bool[supplyAndDemand.GetLength(0), supplyAndDemand.GetLength(1)];
- var minElements = MinElements(supplyAndDemand, fill);
- do
- {
- for (int i = 0; i < minElements.Count; i++)
- {
- var point = minElements[i];
- int row = point.Item1;
- int col = point.Item2;
- DoStuffOnCoords(supplyAndDemand, consumers, providers, fill, row, col);
- }
- minElements = MinElements(supplyAndDemand, fill);
- }
- while (minElements.Count > 0);
- }
- private static void DoStuffOnCoords(int[,] supplyAndDemand, int[] consumers, int[] providers, bool[,] fill, int row, int col)
- {
- int consumer = consumers[row];
- int provider = providers[col];
- var min = Math.Min(consumer, provider);
- if ((consumers[row] -= min) == 0)
- {
- for (int j = 0; j < providers.Length; j++)
- {
- if (fill[row, j])
- continue;
- supplyAndDemand[row, j] = 0;
- fill[row, j] = true;
- }
- }
- if ((providers[col] -= min) == 0)
- {
- for (int j = 0; j < consumers.Length; j++)
- {
- if (fill[j, col])
- continue;
- supplyAndDemand[j, col] = 0;
- fill[j, col] = true;
- }
- }
- supplyAndDemand[row, col] = min;
- }
- private static List<(int, int)> MinElements(int[,] table, bool[,] fill)
- {
- int min = int.MaxValue;
- var points = new List<(int, int)>();
- for (int i = 0; i < table.GetLength(0); i++)
- {
- for (int j = 0; j < table.GetLength(1); j++)
- {
- if (fill[i, j])
- continue;
- if (min == table[i, j])
- {
- points.Add((i, j));
- }
- else if (min > table[i, j])
- {
- min = table[i, j];
- points.Clear();
- points.Add((i, j));
- }
- }
- }
- return points;
- }
- private static void PhogelMethod(int[,] supplyAndDemand, int[] consumers, int[] providers)
- {
- bool[,] fill = new bool[supplyAndDemand.GetLength(0), supplyAndDemand.GetLength(1)];
- int[] consumerFees = new int[consumers.Length];
- int[] providerFees = new int[providers.Length];
- while (AnyIsUnfill(fill))
- {
- RecalculateFees(supplyAndDemand, consumerFees, providerFees, fill);
- int rowInd = MaxIndex(consumerFees);
- int colInd = MaxIndex(providerFees);
- if (consumerFees[rowInd] >= providerFees[colInd])
- {
- int ind = 0;
- int min = int.MaxValue;
- for (int i = 0; i < supplyAndDemand.GetLength(1); i++)
- {
- if (fill[rowInd, i])
- continue;
- if (min > supplyAndDemand[rowInd, i])
- {
- ind = i;
- min = supplyAndDemand[rowInd, i];
- }
- }
- DoStuffOnCoords(supplyAndDemand, consumers, providers, fill, rowInd, ind);
- }
- else
- {
- int ind = 0;
- int min = int.MaxValue;
- for (int i = 0; i < supplyAndDemand.GetLength(0); i++)
- {
- if (fill[i, colInd])
- continue;
- if (min > supplyAndDemand[i, colInd])
- {
- ind = i;
- min = supplyAndDemand[i, colInd];
- }
- }
- DoStuffOnCoords(supplyAndDemand, consumers, providers, fill, ind, colInd);
- }
- }
- }
- private static void RecalculateFees(int[,] supplyAndDemand, int[] consumerFees, int[] providerFees, bool[,] fill)
- {
- for (int i = 0; i < consumerFees.Length; i++)
- {
- int[] row = new int[supplyAndDemand.GetLength(1)];
- bool[] fillMask = new bool[row.Length];
- for (int j = 0; j < row.Length; j++)
- {
- row[j] = supplyAndDemand[i, j];
- fillMask[j] = fill[i, j];
- }
- consumerFees[i] = CalculateFee(row, fillMask);
- }
- for (int i = 0; i < providerFees.Length; i++)
- {
- int[] col = new int[supplyAndDemand.GetLength(0)];
- bool[] fillMask = new bool[col.Length];
- for (int j = 0; j < col.Length; j++)
- {
- col[j] = supplyAndDemand[j, i];
- fillMask[j] = fill[j, i];
- }
- providerFees[i] = CalculateFee(col, fillMask);
- }
- }
- private static int CalculateFee(int[] arr, bool[] filled)
- {
- int min = int.MaxValue;
- int filledAmount = 0;
- for (int i = 0; i < arr.Length; i++)
- {
- if (filled[i])
- {
- filledAmount++;
- continue;
- }
- if (arr[i] < min)
- min = arr[i];
- }
- if (filledAmount == arr.Length - 1)
- return min;
- int min1 = int.MaxValue;
- bool flag = false;
- for (int i = 0; i < arr.Length; i++)
- {
- if (min == arr[i] || filled[i])
- continue;
- if (arr[i] < min1)
- {
- min1 = arr[i];
- flag = true;
- }
- }
- return flag ? min1 - min : 0;
- }
- private static int MaxIndex(int[] arr)
- {
- int max = 0;
- int ind = 0;
- for (int i = 0; i < arr.Length; i++)
- {
- if (arr[i] > max)
- {
- max = arr[i];
- ind = i;
- }
- }
- return ind;
- }
- private static bool AnyIsUnfill(bool[,] fill)
- {
- for (int i = 0; i < fill.GetLength(0); i++)
- {
- for (int j = 0; j < fill.GetLength(1); j++)
- {
- if (!fill[i, j])
- {
- return true;
- }
- }
- }
- return false;
- }
- private static void PrintTable(int[,] table)
- {
- for (int i = 0; i < table.GetLength(0); i++)
- {
- for (int j = 0; j < table.GetLength(1); j++)
- {
- Console.Write(string.Format("{0,-3} ", table[i, j]));
- }
- Console.WriteLine();
- }
- }
- }
- }
|