public void RestoreMarkedHighlighted()
 {
     for (int i = 0; i < NumberOfRows; i++)
     {
         HighlightedRows[i] = false;
         MarkedRows[i]      = false;
     }
     for (int i = 0; i < NumberOfColls; i++)
     {
         HighlightedColls[i] = false;
         MarkedColls[i]      = false;
     }
     AssignedCells.Clear();
     CrossedCells.Clear();
     NewlyMarkedColls.Clear();
     NewlyMarkedRows.Clear();
 }
        public void CoverZeroes()
        {
            DoAssignment();
            MarkUnassignedRows();

            while (true)
            {
                if (NewlyMarkedRows.Count() == 0)
                {
                    break;
                }
                MarkCollsHavingZeroesInNewRows();
                NewlyMarkedRows.Clear();

                if (NewlyMarkedColls.Count() == 0)
                {
                    break;
                }
                MarkRowsHavingAssignmentsInNewColls();
                NewlyMarkedColls.Clear();
            }

            Highlight();

            //internal functions

            void DoAssignment()
            {
                for (int rowNum = 0; rowNum < NumberOfRows; rowNum++)
                {
                    MatrixCell cell = FindZeroInARow(rowNum, 0);

                    if (cell != null)
                    {
                        AssignCell(cell);
                        // cross in a row
                        MatrixCell cellToCross = FindZeroInARow(rowNum, cell.Coll + 1);
                        while (cellToCross != null)
                        {
                            if (!IsCorssed(cellToCross))
                            {
                                CrossCell(cellToCross);
                            }

                            cellToCross = FindZeroInARow(rowNum, cellToCross.Coll + 1);
                        }

                        //Cross in a coll
                        cellToCross = FindZeroInAColl(cell.Coll, cell.Row + 1);
                        while (cellToCross != null)
                        {
                            if (!IsCorssed(cellToCross))
                            {
                                CrossCell(cellToCross);
                            }

                            cellToCross = FindZeroInAColl(cell.Coll, cellToCross.Row + 1);
                        }
                    }
                }

                void AssignCell(MatrixCell cell)
                {
                    AssignedCells.Add(cell);
                }

                void CrossCell(MatrixCell cell)
                {
                    CrossedCells.Add(cell);
                }

                bool IsCorssed(MatrixCell cell)
                {
                    return(CrossedCells.Contains(cell));
                }

                bool IsAssigned(MatrixCell cell)
                {
                    return(AssignedCells.Contains(cell));
                }

                MatrixCell FindZeroInARow(int rowNum, int startingFrom)
                {
                    if (startingFrom >= NumberOfColls)
                    {
                        return(null);
                    }
                    for (int i = startingFrom; i < NumberOfColls; i++)
                    {
                        if (Matrix[rowNum, i] == 0)
                        {
                            MatrixCell cell = new MatrixCell(rowNum, i);
                            if (!IsCorssed(cell))
                            {
                                return(cell);
                            }
                        }
                    }
                    return(null);
                }

                MatrixCell FindZeroInAColl(int collNum, int startingFrom)
                {
                    if (startingFrom >= NumberOfRows)
                    {
                        return(null);
                    }
                    for (int i = startingFrom; i < NumberOfRows; i++)
                    {
                        if (Matrix[i, collNum] == 0)
                        {
                            return(new MatrixCell(i, collNum));
                        }
                    }
                    return(null);
                }
            }

            void MarkUnassignedRows()
            {
                IEnumerable <int> rowsToMark = Enumerable.Range(0, NumberOfRows).Except(AssignedCells.Select(c => c.Row).Distinct());

                foreach (int rowNum in rowsToMark)
                {
                    MarkRow(rowNum);
                }
            }

            void MarkCollsHavingZeroesInNewRows()
            {
                foreach (int markedRow in NewlyMarkedRows)
                {
                    for (int i = 0; i < NumberOfColls; i++)
                    {
                        if (Matrix[markedRow, i] == 0)
                        {
                            MarkColl(i);
                        }
                    }
                }
            }

            void MarkRowsHavingAssignmentsInNewColls()
            {
                foreach (int markedColl in NewlyMarkedColls)
                {
                    IEnumerable RowsToMark = AssignedCells.Where(c => c.Coll == markedColl).Select(c => c.Row);
                    foreach (int row in RowsToMark)
                    {
                        MarkRow(row);
                    }
                }
            }

            void Highlight()
            {
                for (int i = 0; i < NumberOfRows; i++)
                {
                    if (!MarkedRows[i])
                    {
                        HighlightedRows[i] = true;
                    }
                }

                for (int i = 0; i < NumberOfColls; i++)
                {
                    if (MarkedColls[i])
                    {
                        HighlightedColls[i] = true;
                    }
                }
            }

            void MarkRow(int rowNum)
            {
                if (!MarkedRows[rowNum])
                {
                    MarkedRows[rowNum] = true;
                    NewlyMarkedRows.Add(rowNum);
                }
            }

            void MarkColl(int collNum)
            {
                if (!MarkedColls[collNum])
                {
                    MarkedColls[collNum] = true;
                    NewlyMarkedColls.Add(collNum);
                }
            }
        }