private LbDifferenceResult CalculateGreatestLBDifference(State state)
        {
            LbDifferenceResult currentGreatestLbDiff = null;

            for (int i = 0; i < state.Matrix.GetMatrix().GetLength(0); i++)
            {
                for (int j = 0; j < state.Matrix.GetMatrix().GetLength(0); j++)
                {
                    if (state.Matrix.GetMatrix()[i, j] == 0)
                    {
                        LbDifferenceResult lbDifference = GetLbDifference(i, j, state);

                        if (currentGreatestLbDiff == null ||
                            lbDifference.LowerBoundDifference > currentGreatestLbDiff.LowerBoundDifference)
                        {
                            if (currentGreatestLbDiff != null)
                            {
                                _prunedSates += 2;
                            }

                            currentGreatestLbDiff = lbDifference;
                        }
                        else
                        {
                            _prunedSates += 2;
                        }
                    }
                }
            }

            return(currentGreatestLbDiff);
        }
        public PathCalculation CalculatePath()
        {
            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();

            while (pq.Count != 0)
            {
                if (stopwatch.Elapsed.Seconds >= 30)
                {
                    break;
                }

                State state = pq.RemoveMin();

                if (state.GetLowerBound() < _bssf)
                {
                    LbDifferenceResult greatestDifferenceResult = CalculateGreatestLBDifference(state);
                    State[]            children = new State[2]
                    {
                        greatestDifferenceResult.IncludeState, greatestDifferenceResult.ExcludeState
                    };

                    foreach (State child in children)
                    {
                        if (IsSolution(child))
                        {
                            bssfUpdates++;
                            _bssf           = child.GetLowerBound();
                            _bestStateSoFar = child;
                        }
                        else if (child.GetLowerBound() < _bssf)
                        {
                            // Dividing by the number cities in the solution is a great way to prioritize those solutions
                            // that are further along. This helps the algorithm "dig deeper" into the search.
                            pq.Add((int)child.GetLowerBound() / (child.GetCitiesInSolution() == 0 ? 1 : child.GetCitiesInSolution()), child);

                            if (pq.Count > _maxStatesStored)
                            {
                                _maxStatesStored = pq.Count;
                            }
                        }
                        else
                        {
                            _prunedSates++;
                        }
                    }
                }
                else
                {
                    _prunedSates++;
                }
            }

            stopwatch.Stop();

            Console.WriteLine("----------------------------------");
            Console.WriteLine("Elapsed Time: " + stopwatch.ElapsedMilliseconds);
            Console.WriteLine("Problem Size: " + _cities.Length);
            Console.WriteLine("Max States: " + _maxStatesStored);
            Console.WriteLine("Total Created: " + _createdStates);
            Console.WriteLine("States Pruned: " + _prunedSates);
            Console.WriteLine("----------------------------------");

            return(GeneratePathResult(_bestStateSoFar, _cities, stopwatch.ElapsedMilliseconds));
        }