// Returns the index of the last city to be visited in the cycle
        private static void recur(State state)
        {
            //state.printState();
            int currCityIndex = state.currCityIndex;

            // All cities have been visited; finish and return
            if (state.getCitiesVisited() == state.size - 1)
            {
                // The current path cannot be completed bc there is no path from the last city to the first
                if (state.matrix[currCityIndex, state.cityOfOriginIndex] == double.PositiveInfinity)
                {
                    state.lowerBound = double.PositiveInfinity;
                }
                else
                {
                    state.addCity(currCityIndex);
                    state.lowerBound += state.matrix[currCityIndex, state.cityOfOriginIndex];
                    return;
                }
            }

            state.addCity(currCityIndex);

            // find the smallest distance to any other city
            double closestCityDistance = double.PositiveInfinity;
            int    closestCityIndex    = -1;

            for (int j = 1; j < state.matrix.GetLength(1); j++)
            {
                // For a different starting city, the following code
                // would have to be added:
                //for (int j = 0; j < state.matrix.GetLength(1); j++)
                //if (j == state.startCityIndex)
                //    continue;
                if (state.matrix[currCityIndex, j] < closestCityDistance)
                {
                    closestCityIndex    = j;
                    closestCityDistance = state.matrix[currCityIndex, j];
                }
            }

            // add [i,j]
            state.lowerBound += closestCityDistance;

            // Blank out appropriate spaces
            SolverHelper.blankOut(state, closestCityIndex);

            // reduce
            SolverHelper.reduce(state);

            state.currCityIndex = closestCityIndex;
            recur(state);
        }
        private void recur(State state)
        {
            // This is a leaf
            // All cities have been visited; finish and return
            if (state.getCitiesVisited() == cityData.size - 1)
            {
                // The path to the last city is blocked
                if (state.matrix[state.currCityIndex, state.cityOfOriginIndex]
                    == SolverHelper.SPACE_PLACEHOLDER)
                {
                    return;
                }

                state.addCity(state.currCityIndex);

                // Since we've hit a leaf node, we've found another possible solution
                cityData.solutions++;

                // Add the last hop to the lower bound to get the cost of the complete cycle
                state.lowerBound += state.matrix[state.currCityIndex, state.cityOfOriginIndex];

                // Check to see if this route is smaller than the current BSSF
                // If so, replace the current BSSF
                if (state.lowerBound < cityData.bssf.costOfRoute)
                {
                    cityData.bssf = new TSPSolution(cityData.cities, state.cityOrder, state.lowerBound);
                }

                return;
            }

            state.addCity(state.currCityIndex);

            for (int j = 1; j < state.matrix.GetLength(1); j++)
            {
                //Console.WriteLine(state.currCityIndex + " " + j);
                //state.printState();

                double currDistVal = state.matrix[state.currCityIndex, j];
                if (currDistVal != SolverHelper.SPACE_PLACEHOLDER &&
                    state.lowerBound + currDistVal < cityData.bssf.costOfRoute)
                {
                    State childState = SolverHelper.clone(state);

                    // add [i,j]
                    childState.lowerBound += currDistVal;

                    // Blank out the appropriate values with the placeholder
                    SolverHelper.blankOut(childState, j);
                    //childState.printState();

                    // reduce
                    SolverHelper.reduce(childState);

                    childState.currCityIndex = j;

                    if (childState.lowerBound < cityData.bssf.costOfRoute)
                    {
                        q.Enqueue(childState);
                    }
                }
            }
        }