public void findGreatestDiff(State state)          //O(n^3)
        {
            int    chosenX      = 0;                       //city x to city y
            int    chosenY      = 0;
            double greatestDiff = double.NegativeInfinity; //initialize to -oo to find what the greatest
                                                           //difference is
            List <PointF> points = new List <PointF>();

            for (int i = 0; i < state.getMap().GetLength(0); i++)     //rows, O(n)
            {
                for (int j = 0; j < state.getMap().GetLength(1); j++) //columns
                {
                    if (state.getPoint(i, j) == 0)                    //if point is 0
                    {
                        points.Add(new PointF(i, j));                 //store all 0's in a point array
                    }
                }
            }
            for (int i = 0; i < points.Count; i++)                                                                            //loop through 0's to find the greatest difference
            {                                                                                                                 //O(n^3)                               there will be atmost n points, because the entire
             //matrix will be 0
                int possibleMax = findExcludeMinusInclude(Convert.ToInt32(points[i].X), Convert.ToInt32(points[i].Y), state); //O(n^2)
                if (possibleMax >= greatestDiff)                                                                              //set the point to point values, if it is 0 is covered by =
                {
                    chosenX      = Convert.ToInt32(points[i].X);
                    chosenY      = Convert.ToInt32(points[i].Y);
                    greatestDiff = possibleMax;
                }
            }
            State include = makeInclude(chosenX, chosenY, state); //O(n^2)

            if (BSSF > include.getLB())                           //if include's lowerbound is better than the BSSF
            {
                include.setEdge(chosenX, chosenY);                //set the edge in the dictionary
                checkCycles(include, chosenX, chosenY);           //O(n), make sure there are no potential cycles
                queue.Add(include);                               //add to the queue to be popped off later
            }

            if (isDictionaryFilled(include)) //O(n), have all of the edges been filled? then the include.LB is better
            {                                //than the current BSSF, set the BSSF
                BSSF      = include.getLB();
                bestState = include;         //save the "bestState"
            }

            State exclude = makeExclude(chosenX, chosenY, state); //O(n^2)

            if (BSSF > exclude.getLB())                           //if exclude's lowerbound is than the BSSF, add it to the queue
            {
                queue.Add(exclude);
            }
            if (isDictionaryFilled(exclude)) //O(n), have all of the edges been filled?
            {                                // then exclude's lowerbound is better, set the BSSF to exclude.LB
                BSSF      = exclude.getLB();
                bestState = exclude;
            }
        }
        public State makeExclude(int x, int y, State state)                                              //O(n^2)
        {
            State excludeState = new State(copyMatrix(state.getMap()), state.getLB(), state.getEdges()); //O(n^2)

            excludeState.setPoint(x, y, double.PositiveInfinity);                                        //make chosen point infinity
            reduceMatrix(excludeState);                                                                  //O(n^2)
            excludeState.setEdges(state.getEdges());                                                     //initialize excludeStates edges
            return(excludeState);
        }
        public void reduceMatrix(State currentState) //O(n^2)
        {
            double lowerBound = currentState.getLB();

            for (int i = 0; i < currentState.getMap().GetLength(0); i++) // reduce rows
            {                                                            //O(n^2)
                double minimum = double.PositiveInfinity;                //find the lowest value in that row to reduce
                for (int j = 0; j < currentState.getMap().GetLength(1); j++)
                {
                    if (currentState.getPoint(i, j) < minimum)
                    {
                        minimum = currentState.getPoint(i, j);
                    }
                }
                if (minimum == 0) //if there is already a 0 in that row, don't waste time looping through it
                {
                    continue;
                }
                if (minimum != double.PositiveInfinity)
                {
                    for (int j = 0; j < currentState.getMap().GetLength(1); j++)
                    { //reduce the other entire row by that value
                        double reducedPoint = currentState.getPoint(i, j) - minimum;
                        currentState.setPoint(i, j, reducedPoint);
                    }
                    lowerBound += minimum; //add that lowest value to the lowerBound
                }
            }
            for (int j = 0; j < currentState.getMap().GetLength(1); j++) //reduce columns
            {                                                            //O(n^2)
                double minimum = double.PositiveInfinity;
                for (int i = 0; i < currentState.getMap().GetLength(0); i++)
                {
                    if (currentState.getPoint(i, j) < minimum)
                    {
                        minimum = currentState.getPoint(i, j); //find the lowest value in the column
                    }
                }
                if (minimum == 0) //if there is already a 0 in that column, don't waste time looping through it
                {
                    continue;
                }
                if (minimum != double.PositiveInfinity)
                {
                    for (int i = 0; i < currentState.getMap().GetLength(0); i++)
                    {//reduce the entire column by that value
                        double lowerPoint = currentState.getPoint(i, j) - minimum;
                        currentState.setPoint(i, j, lowerPoint);
                    }
                    lowerBound += minimum; //add that minimum value to the lowerBound
                }
            }
            currentState.setLB(lowerBound); //set the lowerbound
        }
        public int findExcludeMinusInclude(int x, int y, State state) //O(n^2)
        {                                                             //finds the exlude minus the include of a point in a matrix
            State excludeState = makeExclude(x, y, state);            //O(n^2)

            reduceMatrix(excludeState);                               //O(n^2)

            State includeState = makeInclude(x, y, state);            //O(n^2)

            reduceMatrix(includeState);                               //O(n^2)

            int cost = Convert.ToInt32(excludeState.getLB() - includeState.getLB());

            return(cost);
        }
        public State makeInclude(int x, int y, State state)                                              //O(n^2)
        {
            State includeState = new State(copyMatrix(state.getMap()), state.getLB(), state.getEdges()); //O(n^2)

            includeState.setPoint(y, x, double.PositiveInfinity);                                        //set the "opposite point to infinity"
            for (int j = 0; j < includeState.getMap().GetLength(1); j++)                                 //set the row to infinity, O(n)
            {
                includeState.setPoint(x, j, double.PositiveInfinity);
            }
            for (int i = 0; i < includeState.getMap().GetLength(0); i++) //set the column to infinity, O(n)
            {
                includeState.setPoint(i, y, double.PositiveInfinity);
            }
            reduceMatrix(includeState);              //O(n^2)
            includeState.setEdges(state.getEdges()); //initialize includeState's dictionary of edges
            return(includeState);
        }
 //O(n^2)
 public void reduceMatrix(State currentState)
 {
     double lowerBound = currentState.getLB();
     for (int i = 0; i < currentState.getMap().GetLength(0); i++) // reduce rows
     {//O(n^2)
         double minimum = double.PositiveInfinity; //find the lowest value in that row to reduce
         for (int j = 0; j < currentState.getMap().GetLength(1); j++)
         {
             if (currentState.getPoint(i, j) < minimum)
                 minimum = currentState.getPoint(i, j);
         }
         if (minimum == 0) //if there is already a 0 in that row, don't waste time looping through it
             continue;
         if (minimum != double.PositiveInfinity)
         {
             for (int j = 0; j < currentState.getMap().GetLength(1); j++)
             { //reduce the other entire row by that value
                 double reducedPoint = currentState.getPoint(i, j) - minimum;
                 currentState.setPoint(i, j, reducedPoint);
             }
             lowerBound += minimum; //add that lowest value to the lowerBound
         }
     }
     for (int j = 0; j < currentState.getMap().GetLength(1); j++) //reduce columns
     {//O(n^2)
         double minimum = double.PositiveInfinity;
         for (int i = 0; i < currentState.getMap().GetLength(0); i++)
         {
             if (currentState.getPoint(i, j) < minimum)
                 minimum = currentState.getPoint(i, j); //find the lowest value in the column
         }
         if (minimum == 0) //if there is already a 0 in that column, don't waste time looping through it
             continue;
         if (minimum != double.PositiveInfinity)
         {
             for (int i = 0; i < currentState.getMap().GetLength(0); i++)
             {//reduce the entire column by that value
                 double lowerPoint = currentState.getPoint(i, j) - minimum;
                 currentState.setPoint(i, j, lowerPoint);
             }
             lowerBound += minimum; //add that minimum value to the lowerBound
         }
     }
     currentState.setLB(lowerBound); //set the lowerbound
 }
 //O(n^2)
 public State makeInclude(int x, int y, State state)
 {
     State includeState = new State(copyMatrix(state.getMap()), state.getLB(), state.getEdges()); //O(n^2)
     includeState.setPoint(y, x, double.PositiveInfinity); //set the "opposite point to infinity"
     for (int j = 0; j < includeState.getMap().GetLength(1); j++) //set the row to infinity, O(n)
     {
         includeState.setPoint(x, j, double.PositiveInfinity);
     }
     for (int i = 0; i < includeState.getMap().GetLength(0); i++) //set the column to infinity, O(n)
     {
         includeState.setPoint(i, y, double.PositiveInfinity);
     }
     reduceMatrix(includeState); //O(n^2)
     includeState.setEdges(state.getEdges()); //initialize includeState's dictionary of edges
     return includeState;
 }
 //O(n^2)
 public State makeExclude(int x, int y, State state)
 {
     State excludeState = new State(copyMatrix(state.getMap()), state.getLB(), state.getEdges()); //O(n^2)
     excludeState.setPoint(x, y, double.PositiveInfinity); //make chosen point infinity
     reduceMatrix(excludeState); //O(n^2)
     excludeState.setEdges(state.getEdges()); //initialize excludeStates edges
     return excludeState;
 }
        Stopwatch timer;            //global timer
        public void branchAndBoundSolve()
        {
            initialState = new State(new Double[Cities.Length, Cities.Length]);
            timer        = new Stopwatch();
            timer.Start();
            for (int i = 0; i < Cities.Length; i++) //O(n^2), initialize initialStates map
            {
                for (int x = 0; x < Cities.Length; x++)
                {
                    initialState.setPoint(i, x, Cities[i].costToGetTo(Cities[x]));
                    if (initialState.getPoint(i, x) == 0)
                    {
                        initialState.setPoint(i, x, double.PositiveInfinity);
                    }
                }
            }
            initialState.initializeEdges();     //initializeEdges initializes the state's dictionary
                                                //with key 0 to n (# of cities), value -> -1
            reduceMatrix(initialState);         //reduce the matrix to find lower bound

            queue = new IntervalHeap <State>(); //this is a global queue
            BSSF  = greedy();                   //find initial best solution so far, O(n^4)
            Console.WriteLine("BSSF: " + BSSF);
            findGreatestDiff(initialState);     //exclude minus include, O(n^3)
            TimeSpan ts = timer.Elapsed;
            bool     terminatedEarly = false;   //boolean to keep track if we stopped after 30 seconds
            int      maxStates       = 0;       //keeps track of the maximum amount of states in the queue at one point
            int      totalSeconds    = 0;

            while (queue.Count != 0)         //O(2^n * n^3), because each time you expand a node, it expands it 2 times, exponentially
            {                                //where n is the number of cities
                if (queue.Count > maxStates) //if maxStates needs to be updated, update it
                {
                    maxStates = queue.Count;
                }
                ts = timer.Elapsed;

                State min = queue.DeleteMin();
                if (totalSeconds < ts.Seconds)
                {
                    totalSeconds = ts.Seconds;
                    Console.WriteLine("seconds: " + totalSeconds);
                }

                if (min.getLB() < BSSF)    //if the min popped off the queue has a lowerbound less than
                {
                    findGreatestDiff(min); //the BSSF, expand it, otherwise, prune it. -> O(n^3)
                }
                else
                {//all of the lowerbounds are worse than the BSSF, break!
                    break;
                }
            }
            if (!terminatedEarly)//if it solved the problem in less than 30 seconds
            {
                int city = 0;
                for (int i = 0; i < bestState.getEdges().Count; i++) //O(n)
                {
                    if (i == 0)                                      //outputting a map into the Route list
                    {
                        Route.Add(Cities[i]);
                        city = bestState.getEdge(i);
                    }
                    else
                    {
                        Route.Add(Cities[city]);
                        city = bestState.getEdge(city);
                    }
                }
                bssf = new TSPSolution(Route);
                // update the cost of the tour.
                Program.MainForm.tbCostOfTour.Text  = " " + bssf.costOfRoute();
                Program.MainForm.tbElapsedTime.Text = ts.TotalSeconds.ToString();
                // do a refresh.
                Program.MainForm.Invalidate();
            }
        }