Просмотр исходного кода

refactor, add comments, add some features

riibka 7 месяцев назад
Родитель
Сommit
54ed2952d0
1 измененных файлов с 139 добавлено и 4 удалено
  1. 139 4
      MathModeling/Program.cs

+ 139 - 4
MathModeling/Program.cs

@@ -21,6 +21,10 @@ namespace MathModeling
             if (consumers.Sum() == providers.Sum())
             {
                 PhogelMethod(supplyAndDemand, consumers, providers);
+                //NorthwestAngleMethod(supplyAndDemand, consumers, providers);
+                //DoublePreferenceMethod(supplyAndDemand, consumers, providers);
+                //MinElementMethod(supplyAndDemand, consumers, providers);
+
                 PrintTable(supplyAndDemand);
             }
             else
@@ -39,9 +43,7 @@ namespace MathModeling
                 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);
+                    DoStuffOnCoords(supplyAndDemand, consumers, providers, fill, point.Item1, point.Item2);
                 }
                 minElements = MinElements(supplyAndDemand, fill);
             }
@@ -153,20 +155,24 @@ namespace MathModeling
             }
         }
 
+        //Перерасчет штрафов
         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)];
@@ -182,6 +188,7 @@ namespace MathModeling
 
         private static int CalculateFee(int[] arr, bool[] filled)
         {
+            //Находит минимум строки и количество заполненных клеток
             int min = int.MaxValue;
             int filledAmount = 0;
             for (int i = 0; i < arr.Length; i++)
@@ -194,8 +201,10 @@ namespace MathModeling
                 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++)
@@ -208,6 +217,7 @@ namespace MathModeling
                     flag = true;
                 }
             }
+            //Если найден второй -- возвращает разницу
             return flag ? min1 - min : 0;
         }
 
@@ -226,6 +236,131 @@ namespace MathModeling
             return ind;
         }
 
+        //В тупую идет слева-направо, сверху-вниз
+        private static void NorthwestAngleMethod(int[,] supplyAndDemand, int[] consumers, int[] providers)
+        {
+            bool[,] fill = new bool[supplyAndDemand.GetLength(0), supplyAndDemand.GetLength(1)];
+            int i = 0;
+            for (int j = 0; j < supplyAndDemand.GetLength(0); j++)
+            {
+                DoStuffOnCoords(supplyAndDemand, consumers, providers, fill, j, i);
+                i++;
+                DoStuffOnCoords(supplyAndDemand, consumers, providers, fill, j, i);
+            }
+        }
+
+        //Тот же мин элемент, но больше фигни
+        private static void DoublePreferenceMethod(int[,] supplyAndDemand, int[] consumers, int[] providers)
+        {
+            bool[,] fill = new bool[supplyAndDemand.GetLength(0), supplyAndDemand.GetLength(1)];
+            var minElements = DoubleMinElements(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 = DoubleMinElements(supplyAndDemand, fill);
+            }
+            while (minElements.Count > 0);
+        }
+
+        //
+        private static List<(int, int)> DoubleMinElements(int[,] table, bool[,] fill)
+        {
+            //Ищет минимальные в строке
+            bool[,] isMin = new bool[table.GetLength(0), table.GetLength(1)];
+            //по строкам
+            for (int i = 0; i < table.GetLength(0); i++)
+            {
+                int min = int.MaxValue;
+                List<int> indices = new List<int>();
+                for (int j = 0; j < table.GetLength(1); j++)
+                {
+                    if (fill[i, j])
+                        continue;
+                    if (min == table[i, j])
+                    {
+                        indices.Add(j);
+                    }
+                    else if (min > table[i, j])
+                    {
+                        min = table[i, j];
+                        indices.Clear();
+                        indices.Add(j);
+                    }
+                }
+                indices.ForEach(ind => isMin[i, ind] = true);
+            }
+            //Список точно минимальных точек, проходит 
+            var points = new List<(int, int)>();
+            //по столбцам
+            for (int j = 0; j < table.GetLength(1); j++)
+            {
+                int min = int.MaxValue;
+                List<int> indices = new List<int>();
+                for (int i = 0; i < table.GetLength(0); i++)
+                {
+                    if (fill[i, j])
+                        continue;
+                    if (min == table[i, j])
+                    {
+                        indices.Add(i);
+                    }
+                    else if (min > table[i, j])
+                    {
+                        min = table[i, j];
+                        indices.Clear();
+                        indices.Add(i);
+                    }
+                }
+                //Если есть пересечение -- добавляет в список, затирает. иначе отмечает минимальным
+                indices.ForEach(ind =>
+                {
+                    if (isMin[ind, j])
+                    {
+                        points.Add((ind, j));
+                        isMin[ind, j] = false;
+                    }
+                    else
+                    {
+                        isMin[ind, j] = true;
+                    }
+                });
+            }
+
+
+            //делегат сравнения
+            Comparison<(int, int)> comparison = (left, right) =>
+            {
+                int a = table[left.Item1, left.Item2];
+                int b = table[right.Item1, right.Item2];
+                return a > b ? 1 : a < b ? -1 : 0;
+            };
+            //cортирует с начала точки
+            points.Sort(comparison);
+            int cnt = points.Count;
+
+            //добавляет остальные минимумы
+            for (int i = 0; i < table.GetLength(0); i++)
+            {
+                for (int j = 0; j < table.GetLength(1); j++)
+                {
+                    if (isMin[i, j])
+                    {
+                        points.Add((i, j));
+                    }
+                }
+            }
+            //сортирует одноминимальные точки (без пересечений)
+            points.Sort(cnt, points.Count - cnt, Comparer<(int, int)>.Create(comparison));
+
+            return points;
+        }
+
         private static bool AnyIsUnfill(bool[,] fill)
         {
             for (int i = 0; i < fill.GetLength(0); i++)