8. Если в одной строке с ним есть 0*, то к шагу 9 иначе – к шагу 10

 

 

Лабораторная работа №1

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

Вариант 15

 

 

Выполнил: Смирнов А.В. ИУ7-81

 

Содержательная постановка задачи о назначениях

В распоряжении работодателя имеется n работ и n исполнителей. Стоимость выполнений i-ой работы j-ым исполнителем составляет денежных единиц. Требуется распределить работы между исполнителями так, чтобы:

1. Каждый исполнитель выполнял ровно одну работу

2. Общая стоимость выполнения работ была минимальная

Математическая постановка задачи о назначениях

Тогда общая стоимость выполненных работ:

Условие того, что i работу выполняет один сотрудник:

Условие того, что j сотрудник выполняет одну работу:

В результате:

 

Индивидуальное задание (Вариант 15)

10 12 7 11 10
12 5 12 7 12
8 6 7 8 13
8 11 5 9 9
10 8 9 11 11

 

 

Краткое описание венгерского метода

1. Подготовительный этап:

a. Найти минимальный элемент в каждом столбце, вычесть его из всех элементов столбца

b. Найти минимальный элемент в каждой строке, вычесть его из всех элементов строки

2. Отметить * нулевые элементы каждого столбца, если в строке с ними нет элементов 0*

3. К – число 0*

4. Если K < количества работ, то к шагу 5, иначе – к шагу 12

5. Выделить столбцы, в которых есть 0*

6. Если среди невыделенных элементов есть 0, то к шагу 7, иначе – к шагу 11

7. Пометить найденный 0 как 0’

8. Если в одной строке с ним есть 0*, то к шагу 9 иначе – к шагу 10

9. Снять выделение со столбца в котором находится 0* и выделить строку

10. Построить L цепочку. Заменить в ней все 0* на 0’ и наоборот. Снять все выделения. Перейти к шагу 4

11. Найти минимальный элемент среди невыделенных. Вычесть его из невыделенных столбцов и прибавить его к выделенным строкам. Перейти к шагу 6.

12. Решение найдено, вывести результат

Текст программы:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows.Forms;

 

namespace lab1

{

public partial class Form1 : Form

{

public int [,]C;

public Form1()

{

InitializeComponent();

}

 

public DataGridView DGrid;

public bool by_step;

 

public struct Element

{

public int[,] Number;

public bool[,] Stared;

public bool[,] Hatch;

}

public struct Matrix

{

public Element El;

public bool[] MarkedColumn;

public bool[] MarkedString;

}

 

public class Pos

{

public int row;

public int col;

public bool empty;

 

public Pos()

{

row = -1;

col = -1;

empty = true;

}

 

public Pos(int r, int c)

{

row = r;

col = c;

empty = false;

}

 

public override string ToString()

{

return "Empty: " + empty.ToString() + "\nCol: " + col.ToString() + "\nRow: " + row.ToString();

}

}

 

public int size = 0;

Matrix TempMatr;

 

private void button1_Click(object sender, EventArgs e)

{

Clear();

size = int.Parse(textBox1.Text.ToString());

FirstGrd.RowCount = size;

FirstGrd.ColumnCount = size;

 

C = new int[size, size];

 

 

for (int i = 0; i < size; i++)

{

FirstGrd.Columns[i].Width = 30;

 

}

}

 

public void Prepearing_max()

{

int max = -1;

for (int i = 0; i < size; i++)

{

for (int j = 0; j < size; j++)

{

if (TempMatr.El.Number[i, j] > max)

max = TempMatr.El.Number[i, j];

}

}

 

for (int i = 0; i < size; i++)

{

for (int j = 0; j < size; j++)

{

TempMatr.El.Number[i, j] = max - TempMatr.El.Number[i, j];

}

}

}

 

public void simpleOut()

{

for (int i = 0; i < size; i++)

{

DGrid.Columns[i].Width = 30;

for (int j = 0; j < size; j++)

{

 

DGrid.Rows[i].Cells[j].Value = TempMatr.El.Number[i, j].ToString();

DGrid.Rows[i].Cells[j].Style.BackColor = System.Drawing.Color.White;

 

if ((TempMatr.MarkedColumn[j]) || (TempMatr.MarkedString[i]))

DGrid.Rows[i].Cells[j].Style.BackColor = System.Drawing.Color.Yellow;

 

if (TempMatr.El.Stared[i, j])

DGrid.Rows[i].Cells[j].Value = TempMatr.El.Number[i, j].ToString() + "*";

if (TempMatr.El.Hatch[i, j])

DGrid.Rows[i].Cells[j].Value = TempMatr.El.Number[i, j].ToString() + "'";

}

}

}

public void tempOut(string action)

{

if (by_step)

{

simpleOut();

 

MessageBox.Show(action,"Отладочный режим");

}

}

 

 

//основа

public void Solve()

{

int k = 0;

//В каждом столбце отмечаем * нули такие, что в строке с ним больше нет 0*

for (int i = 0; i < size; i++)

{

for (int j = 0; j < size; j++)

{

if ((TempMatr.El.Number[j, i] == 0) && (StrWithoutStarredNulls(j)))

{

k++;

TempMatr.El.Stared[j, i] = true;

break;

}

}

}

tempOut("Выбрали начальную комбинацию 0*.\nИх оказалось " + k.ToString());

 

bool actions = true;

Pos last = new Pos();

while (k < size)

{

if (actions)

{

for (int i = 0; i < size; i++)

{

for (int j = 0; j < size; j++)

{

if (TempMatr.El.Stared[j, i])

TempMatr.MarkedColumn[i] = true;

}

}

actions = false;

tempOut("Отметили столбы в которых есть 0*");

}

 

Pos zero = CheckUnselected();

if (!zero.empty)

{

tempOut("Среди невыделенных элементов был 0");

 

TempMatr.El.Hatch[zero.row, zero.col] = true;

last = new Pos(zero.row, zero.col);

tempOut("Помечаем его");

 

int checker = CheckLine(zero.row);

if (checker != -1)

{

TempMatr.MarkedColumn[checker] = false;

TempMatr.MarkedString[zero.row] = true;

tempOut("В строке с ним есть 0*. Снимем выделение со столбца, \nв котором находится 0*, выделяем строку");

}

else

{

tempOut("В строке с ним нет 0*. Строим L-цепочку");

Pos[] LChain = new Pos[100];

int LSize = 1;

LChain[0] = new Pos(last.row, last.col);

 

Pos next = new Pos();

while (true)

{

next = findNext(LChain[LSize -1]);

 

if (!next.empty)

{

LChain[LSize] = new Pos(next.row, next.col);

LSize++;

}

else

break;

 

}

 

for (int i = 0; i < LSize; i++)

{

if (TempMatr.El.Hatch[LChain[i].row, LChain[i].col])

{

TempMatr.El.Stared[LChain[i].row, LChain[i].col] = true;

TempMatr.El.Hatch[LChain[i].row, LChain[i].col] = false;

}

else

{

TempMatr.El.Stared[LChain[i].row, LChain[i].col] = false;

TempMatr.El.Hatch[LChain[i].row, LChain[i].col] = true;

}

}

 

tempOut("После замены в L цепочке");

for (int i = 0; i < size; i++)

{

TempMatr.MarkedColumn[i] = false;

TempMatr.MarkedString[i] = false;

 

for (int j = 0; j < size; j++)

{

TempMatr.El.Hatch[i, j] = false;

}

}

if (k == size)

tempOut("Решение найдено");

else

tempOut("Сняли выделение");

k++;

actions = true;

}

}

else

{

tempOut("Среди невыделенных элементов нет 0");

int h = findMin();

for (int i = 0; i < size; i++)

{

if (!TempMatr.MarkedColumn[i])

{

for (int j = 0; j < size; j++)

{

TempMatr.El.Number[j, i] -= h;

}

}

 

if (TempMatr.MarkedString[i])

{

for (int j = 0; j < size; j++)

{

TempMatr.El.Number[i, j] += h;

}

}

}

tempOut("Минимальный элемент среди невыделенных: " + h.ToString() +

"\nВычли его из невыделенных столбцов и прибавили к выделеным строкам");

}

}

}

 

 

public int findMin()

{

int min = -1;

for (int i = 0; i < size; i++)

{

if (!TempMatr.MarkedString[i])

{

for (int j = 0; j < size; j++)

{

if (!TempMatr.MarkedColumn[j])

{

if (min == -1)

min = TempMatr.El.Number[i, j];

 

if (TempMatr.El.Number[i, j] < min)

min = TempMatr.El.Number[i, j];

}

}

}

}

return min;

}

 

public Pos findNext(Pos current)

{

if (TempMatr.El.Stared[current.row, current.col])

{

// find '

for (int i = 0; i < size; i++)

{

if (TempMatr.El.Hatch[current.row, i])

return new Pos(current.row, i);

}

}

else

{

// find *

for (int i = 0; i < size; i++)

{

if (TempMatr.El.Stared[i, current.col])

return new Pos(i, current.col);

}

}

 

return (new Pos());

}

 

 

 

public int CheckLine(int Line)

{

for (int i = 0; i < size; i++)

{

if (TempMatr.El.Stared[Line, i])

return i;

}

 

return -1;

}

 

public Pos CheckUnselected()

{

Pos ret = new Pos();

for (int i = 0; i < size; i++)

{

if (!TempMatr.MarkedString[i])

{

for (int j = 0; j < size; j++)

{

if (!TempMatr.MarkedColumn[j])

if (TempMatr.El.Number[i, j] == 0)

{

ret.empty = false;

ret.col = j;

ret.row = i;

return ret;

}

}

}

}

 

return ret;

}

 

public bool StrWithoutStarredNulls(int index)

{

for (int i = 0; i < size; i++)

{

if (TempMatr.El.Stared[index, i])

return false;

}

return true;

}

 

//1. Подготовительный этап

public void Prepearing()

{

int Min;

for (int i = 0; i < size; i++)

{//в каждом столбце вычитаем из всех минимальный

Min = TempMatr.El.Number[0, i];

for (int j = 0; j < size; j++)

{

if (TempMatr.El.Number[j, i] < Min)

Min = TempMatr.El.Number[j, i];

}

 

for (int j = 0; j < size; j++)

{

TempMatr.El.Number[j, i] = TempMatr.El.Number[j, i] - Min;

}

}

 

for (int i = 0; i < size; i++)

{//в каждой строке вычитаем из всех минимальный

Min = TempMatr.El.Number[i, 0];

for (int j = 0; j < size; j++)

{

if (TempMatr.El.Number[i, j] < Min)

Min = TempMatr.El.Number[i, j];

}

 

 

for (int j = 0; j < size; j++)

{

TempMatr.El.Number[i, j] = TempMatr.El.Number[i, j] - Min;

}

}

}

 

 

//Основная функция

private void button2_Click(object sender, EventArgs e)

{

Clear();

 

by_step = checkBox2.Checked;

 

TempMatr.El.Number = new int[size, size];

TempMatr.El.Stared = new bool[size, size];

TempMatr.El.Hatch = new bool[size, size];

TempMatr.MarkedColumn = new bool[size];

TempMatr.MarkedString = new bool[size];

for (int i = 0; i < size; i++)

{

for (int j = 0; j < size; j++)

{//Переносим данные с формы во внутренюю матрицу для вычислений

TempMatr.El.Number[i, j] = int.Parse(FirstGrd.Rows[i].Cells[j].Value.ToString());

}

}

 

DGrid = SecondGrd;

 

SecondGrd.RowCount = size;

SecondGrd.ColumnCount = size;

//снимаем все выделения с матрицы

for (int i = 0; i < size; i++)

{

TempMatr.MarkedColumn[i] = false;

TempMatr.MarkedString[i] = false;

for (int j = 0; j < size; j++)

{

TempMatr.El.Stared[i, j] = false;

TempMatr.El.Hatch[i, j] = false;

 

SecondGrd.Rows[i].Cells[j].Style.BackColor = System.Drawing.Color.White;

}

}

//Подготовительный этап

if (IfMinimization.Checked)

Prepearing();

else

Prepearing_max();

 

tempOut("Подготовительный этап завершен");

 

Solve();

 

if (!by_step)

simpleOut();

 

int total = 0;

for (int i = 0; i < size; i++)

{

for (int j = 0; j < size; j++)

{

if (TempMatr.El.Stared[i, j])

{

SecondGrd.Rows[i].Cells[j].Style.BackColor = System.Drawing.Color.Yellow;

FirstGrd.Rows[i].Cells[j].Style.BackColor = System.Drawing.Color.Yellow;

total += Convert.ToInt32(FirstGrd.Rows[i].Cells[j].Value);

}

}

}

SumLabel.Text = total.ToString();

FirstGrd.ClearSelection();

SecondGrd.ClearSelection();

}

 

private void Form1_Load(object sender, EventArgs e)

{

IfMinimization.Checked = true;

}

 

private void dataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)

{

Clear();

}

 

private void Clear()

{

SumLabel.Text = "";

for (int i = 0; i < size; i++)

{

for (int j = 0; j < size; j++)

{

FirstGrd.Rows[i].Cells[j].Style.BackColor = System.Drawing.Color.White;

}

}

}

 

 

 

private void fill_dg_with_var15(DataGridView DGrid)

{

DGrid.RowCount = 5;

DGrid.ColumnCount = 5;

size = 5;

C = new int[size, size];

 

for (int i = 0; i < 5; i++)

{

FirstGrd.Columns[i].Width = 30;

}

DGrid.Rows[0].Cells[0].Value = "10";

DGrid.Rows[0].Cells[1].Value = "12";

DGrid.Rows[0].Cells[2].Value = "7";

DGrid.Rows[0].Cells[3].Value = "11";

DGrid.Rows[0].Cells[4].Value = "10";

 

DGrid.Rows[1].Cells[0].Value = "12";

DGrid.Rows[1].Cells[1].Value = "5";

DGrid.Rows[1].Cells[2].Value = "12";

DGrid.Rows[1].Cells[3].Value = "7";

DGrid.Rows[1].Cells[4].Value = "12";

 

DGrid.Rows[2].Cells[0].Value = "8";

DGrid.Rows[2].Cells[1].Value = "6";

DGrid.Rows[2].Cells[2].Value = "7";

DGrid.Rows[2].Cells[3].Value = "8";

DGrid.Rows[2].Cells[4].Value = "13";

 

DGrid.Rows[3].Cells[0].Value = "8";

DGrid.Rows[3].Cells[1].Value = "11";

DGrid.Rows[3].Cells[2].Value = "5";

DGrid.Rows[3].Cells[3].Value = "9";

DGrid.Rows[3].Cells[4].Value = "9";

 

DGrid.Rows[4].Cells[0].Value = "10";

DGrid.Rows[4].Cells[1].Value = "8";

DGrid.Rows[4].Cells[2].Value = "9";

DGrid.Rows[4].Cells[3].Value = "11";

DGrid.Rows[4].Cells[4].Value = "11";

 

}

 

private void button3_Click(object sender, EventArgs e)

{

Clear();

 

fill_dg_with_var15(FirstGrd);

}

 

private void button4_Click(object sender, EventArgs e)

{

simpleOut();

}

}

}

 

Результаты выполнения программы