Program.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Runtime.InteropServices;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. namespace MathModeling
  8. {
  9. internal class Program
  10. {
  11. static void Main(string[] args)
  12. {
  13. int[,] supplyAndDemand = { {16, 26, 12, 24, 3 },
  14. { 5, 2, 19, 27, 2 },
  15. { 29, 23, 25, 16, 8 },
  16. { 2, 25, 14, 15, 21 } };
  17. int[] consumers = { 14, 14, 14, 14 };
  18. int[] providers = { 13, 5, 13, 12, 13 };
  19. if (consumers.Sum() == providers.Sum())
  20. {
  21. PhogelMethod(supplyAndDemand, consumers, providers);
  22. PrintTable(supplyAndDemand);
  23. }
  24. else
  25. {
  26. Console.WriteLine("Некорректные данные!");
  27. }
  28. Console.ReadKey();
  29. }
  30. private static void MinElementMethod(int[,] supplyAndDemand, int[] consumers, int[] providers)
  31. {
  32. bool[,] fill = new bool[supplyAndDemand.GetLength(0), supplyAndDemand.GetLength(1)];
  33. var minElements = MinElements(supplyAndDemand, fill);
  34. do
  35. {
  36. for (int i = 0; i < minElements.Count; i++)
  37. {
  38. var point = minElements[i];
  39. int row = point.Item1;
  40. int col = point.Item2;
  41. DoStuffOnCoords(supplyAndDemand, consumers, providers, fill, row, col);
  42. }
  43. minElements = MinElements(supplyAndDemand, fill);
  44. }
  45. while (minElements.Count > 0);
  46. }
  47. private static void DoStuffOnCoords(int[,] supplyAndDemand, int[] consumers, int[] providers, bool[,] fill, int row, int col)
  48. {
  49. int consumer = consumers[row];
  50. int provider = providers[col];
  51. var min = Math.Min(consumer, provider);
  52. if ((consumers[row] -= min) == 0)
  53. {
  54. for (int j = 0; j < providers.Length; j++)
  55. {
  56. if (fill[row, j])
  57. continue;
  58. supplyAndDemand[row, j] = 0;
  59. fill[row, j] = true;
  60. }
  61. }
  62. if ((providers[col] -= min) == 0)
  63. {
  64. for (int j = 0; j < consumers.Length; j++)
  65. {
  66. if (fill[j, col])
  67. continue;
  68. supplyAndDemand[j, col] = 0;
  69. fill[j, col] = true;
  70. }
  71. }
  72. supplyAndDemand[row, col] = min;
  73. }
  74. private static List<(int, int)> MinElements(int[,] table, bool[,] fill)
  75. {
  76. int min = int.MaxValue;
  77. var points = new List<(int, int)>();
  78. for (int i = 0; i < table.GetLength(0); i++)
  79. {
  80. for (int j = 0; j < table.GetLength(1); j++)
  81. {
  82. if (fill[i, j])
  83. continue;
  84. if (min == table[i, j])
  85. {
  86. points.Add((i, j));
  87. }
  88. else if (min > table[i, j])
  89. {
  90. min = table[i, j];
  91. points.Clear();
  92. points.Add((i, j));
  93. }
  94. }
  95. }
  96. return points;
  97. }
  98. private static void PhogelMethod(int[,] supplyAndDemand, int[] consumers, int[] providers)
  99. {
  100. bool[,] fill = new bool[supplyAndDemand.GetLength(0), supplyAndDemand.GetLength(1)];
  101. int[] consumerFees = new int[consumers.Length];
  102. int[] providerFees = new int[providers.Length];
  103. while (AnyIsUnfill(fill))
  104. {
  105. RecalculateFees(supplyAndDemand, consumerFees, providerFees, fill);
  106. int rowInd = MaxIndex(consumerFees);
  107. int colInd = MaxIndex(providerFees);
  108. if (consumerFees[rowInd] >= providerFees[colInd])
  109. {
  110. int ind = 0;
  111. int min = int.MaxValue;
  112. for (int i = 0; i < supplyAndDemand.GetLength(1); i++)
  113. {
  114. if (fill[rowInd, i])
  115. continue;
  116. if (min > supplyAndDemand[rowInd, i])
  117. {
  118. ind = i;
  119. min = supplyAndDemand[rowInd, i];
  120. }
  121. }
  122. DoStuffOnCoords(supplyAndDemand, consumers, providers, fill, rowInd, ind);
  123. }
  124. else
  125. {
  126. int ind = 0;
  127. int min = int.MaxValue;
  128. for (int i = 0; i < supplyAndDemand.GetLength(0); i++)
  129. {
  130. if (fill[i, colInd])
  131. continue;
  132. if (min > supplyAndDemand[i, colInd])
  133. {
  134. ind = i;
  135. min = supplyAndDemand[i, colInd];
  136. }
  137. }
  138. DoStuffOnCoords(supplyAndDemand, consumers, providers, fill, ind, colInd);
  139. }
  140. }
  141. }
  142. private static void RecalculateFees(int[,] supplyAndDemand, int[] consumerFees, int[] providerFees, bool[,] fill)
  143. {
  144. for (int i = 0; i < consumerFees.Length; i++)
  145. {
  146. int[] row = new int[supplyAndDemand.GetLength(1)];
  147. bool[] fillMask = new bool[row.Length];
  148. for (int j = 0; j < row.Length; j++)
  149. {
  150. row[j] = supplyAndDemand[i, j];
  151. fillMask[j] = fill[i, j];
  152. }
  153. consumerFees[i] = CalculateFee(row, fillMask);
  154. }
  155. for (int i = 0; i < providerFees.Length; i++)
  156. {
  157. int[] col = new int[supplyAndDemand.GetLength(0)];
  158. bool[] fillMask = new bool[col.Length];
  159. for (int j = 0; j < col.Length; j++)
  160. {
  161. col[j] = supplyAndDemand[j, i];
  162. fillMask[j] = fill[j, i];
  163. }
  164. providerFees[i] = CalculateFee(col, fillMask);
  165. }
  166. }
  167. private static int CalculateFee(int[] arr, bool[] filled)
  168. {
  169. int min = int.MaxValue;
  170. int filledAmount = 0;
  171. for (int i = 0; i < arr.Length; i++)
  172. {
  173. if (filled[i])
  174. {
  175. filledAmount++;
  176. continue;
  177. }
  178. if (arr[i] < min)
  179. min = arr[i];
  180. }
  181. if (filledAmount == arr.Length - 1)
  182. return min;
  183. int min1 = int.MaxValue;
  184. bool flag = false;
  185. for (int i = 0; i < arr.Length; i++)
  186. {
  187. if (min == arr[i] || filled[i])
  188. continue;
  189. if (arr[i] < min1)
  190. {
  191. min1 = arr[i];
  192. flag = true;
  193. }
  194. }
  195. return flag ? min1 - min : 0;
  196. }
  197. private static int MaxIndex(int[] arr)
  198. {
  199. int max = 0;
  200. int ind = 0;
  201. for (int i = 0; i < arr.Length; i++)
  202. {
  203. if (arr[i] > max)
  204. {
  205. max = arr[i];
  206. ind = i;
  207. }
  208. }
  209. return ind;
  210. }
  211. private static bool AnyIsUnfill(bool[,] fill)
  212. {
  213. for (int i = 0; i < fill.GetLength(0); i++)
  214. {
  215. for (int j = 0; j < fill.GetLength(1); j++)
  216. {
  217. if (!fill[i, j])
  218. {
  219. return true;
  220. }
  221. }
  222. }
  223. return false;
  224. }
  225. private static void PrintTable(int[,] table)
  226. {
  227. for (int i = 0; i < table.GetLength(0); i++)
  228. {
  229. for (int j = 0; j < table.GetLength(1); j++)
  230. {
  231. Console.Write(string.Format("{0,-3} ", table[i, j]));
  232. }
  233. Console.WriteLine();
  234. }
  235. }
  236. }
  237. }