Венгерский алгоритм (задача о назначениях) - C#

Узнай цену своей работы

Формулировка задачи:

Здравствуйте. Необходимо реализовать венгерский алгоритм. Поиски в интернете ни к чему не привели. Наткнулась на псевдокод Лопатина. Но с векторами никогда не сталкивалась и боюсь, что не освою. Может у кого-то есть более простая реализация этого алгоритма? Буду крайне признательна.

Решение задачи: «Венгерский алгоритм (задача о назначениях)»

textual
Листинг программы
  1.     public partial class Form1 : Form
  2.     {
  3.         List<int> PInt = new List<int>();
  4.         List<int> VInt = new List<int>();
  5.         List<List<int>> VVInt = new List<List<int>>();
  6.         List<List<int>> VPInt = new List<List<int>>();
  7.  
  8.  
  9.         public Form1()
  10.         {
  11.             InitializeComponent();
  12.         }
  13.  
  14.         private void Form1_Load(object sender, EventArgs e)
  15.         {
  16.             int taskCount = 4;
  17.             int emplCount = 4;
  18.  
  19.             VVInt = new List<List<int>>(){new List<int>() {6,15,3,12,4,2},
  20.                                           new List<int>() {14,3,3,7,2,1},
  21.                                           new List<int>() {3,2,8,15,8,12},
  22.                                           new List<int>() {3,14,3,15,11,10},
  23.                                           new List<int>() {3,13,1,9,6,6},
  24.                                           new List<int>() {15,10,3,4,5,10}
  25.             };
  26.  
  27.  
  28.             #region Если на максимум
  29.              List<int> maxStrVals = VVInt.Select(str => str.Max()).ToList();
  30.              for (int i = 0; i < VVInt.Count; i++)
  31.                  for (int j = 0; j < (VVInt.Sum(x => x.Count) / VVInt.Count); j++)
  32.                      VVInt[i][j] = maxStrVals[i] - VVInt[i][j];
  33.             #endregion
  34.  
  35.  
  36.             VVInt = hungarian(VVInt);
  37.  
  38.  
  39.             foreach (List<int> i in VVInt)
  40.             {
  41.                 foreach (int j in i)
  42.                     richTextBox1.Text+=j.ToString() + " \t ";
  43.  
  44.                 richTextBox1.Text += "\r\n";
  45.             }
  46.             //MessageBox.Show("");
  47.         }
  48.  
  49.        
  50.         List<List<int>> hungarian(List<List<int>> matrix) {
  51.             try
  52.             {
  53.                 // Размеры матрицы
  54.                 int height = matrix.Count, width = matrix.Sum(x => x.Count) / height;
  55.  
  56.                 // Значения, вычитаемые из строк (u) и столбцов (v)
  57.                 // VInt u(height, 0), v(width, 0);
  58.                 List<int> u = new List<int>(height);
  59.                 List<int> v = new List<int>(width);
  60.  
  61.                 for (int a = 0; a < height; a++)
  62.                     u.Add(0);
  63.                 for (int a = 0; a < width; a++)
  64.                     v.Add(0);
  65.                
  66.  
  67.                 // Индекс помеченной клетки в каждом столбце
  68.                 List<int> markIndices = new List<int>(width);
  69.                 for (int a = 0; a < width; a++)
  70.                     markIndices.Add(-1);
  71.  
  72.                 // Будем добавлять строки матрицы одну за другой
  73.                     int count = 0;
  74.                 for (int i = 0; i < height; i++)
  75.                 {
  76.                     List<int> links = new List<int>(width)   ;
  77.                     List<int> mins = new List<int>(width)    ;
  78.                     List<int> visited = new List<int>(width) ;
  79.  
  80.                     for (int a = 0; a < width; a++)
  81.                     {
  82.                         links.Add(-1);
  83.                         mins.Add(int.MaxValue);
  84.                         visited.Add(0);
  85.                     }
  86.  
  87.                     // Разрешение коллизий (создание "чередующейся цепочки" из нулевых элементов)
  88.                     int markedI = i, markedJ = -1, j = 0;
  89.                     while (markedI != -1)
  90.                     {
  91.                         // Обновим информацию о минимумах в посещенных строках непосещенных столбцов
  92.                         // Заодно поместим в j индекс непосещенного столбца с самым маленьким из них
  93.                         j = -1;
  94.                         for (int j1 = 0; j1 < width; j1++)
  95.                             if (visited[j1] != 1)
  96.                             {
  97.                                 if (matrix[markedI][j1] - u[markedI] - v[j1] < mins[j1])
  98.                                 {
  99.                                     mins[j1] = matrix[markedI][j1] - u[markedI] - v[j1];
  100.                                     links[j1] = markedJ;
  101.                                 }
  102.                                 if (j == -1 || mins[j1] < mins[j])
  103.                                     j = j1;
  104.                             }
  105.  
  106.                         // Теперь нас интересует элемент с индексами (markIndices[links[j]], j)
  107.                         // Произведем манипуляции со строками и столбцами так, чтобы он обнулился
  108.                         int delta = mins[j];
  109.                         for (int j1 = 0; j1 < width; j1++)
  110.                             if (visited[j1] == 1)
  111.                             {
  112.                                 u[markIndices[j1]] += delta;
  113.                                 v[j1] -= delta;
  114.                             }
  115.                             else
  116.                             {
  117.                                 mins[j1] -= delta;
  118.                             }
  119.                         u[i] += delta;
  120.  
  121.                         // Если коллизия не разрешена - перейдем к следующей итерации
  122.                         visited[j] = 1;
  123.                         markedJ = j;
  124.                         markedI = markIndices[j];
  125.                         count++;
  126.                     }
  127.  
  128.                     // Пройдем по найденной чередующейся цепочке клеток, снимем отметки с
  129.                     // отмеченных клеток и поставим отметки на неотмеченные
  130.                     for (; links[j] != -1; j = links[j])
  131.                         markIndices[j] = markIndices[links[j]];
  132.                     markIndices[j] = i;
  133.                 }
  134.  
  135.                 // Вернем результат в естественной форме
  136.                 List<List<int>> result = new List<List<int>>();
  137.                 for (int j = 0; j < width; j++)
  138.                     if (markIndices[j] != -1)
  139.                         result.Add(new List<int>() { markIndices[j], j });
  140.                 return result;
  141.             }
  142.             catch (Exception ex)
  143.             {
  144.                 MessageBox.Show(ex.Message);
  145.                 return new List<List<int>>();
  146.             }
  147.            
  148.         }
  149.     }

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

14   голосов , оценка 4.214 из 5

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут
Похожие ответы