A way of solving this using the so-called back-tracking would mean
- Having an unique identifier for the cities (you don't need a "pass" counter if pass only once is required, and not the minimum of passes). An enumeration of cities should suffice.
- Having the relations among cities (distances). If you have a global access for each of distance and not restricted to identify ("discover") new distances only reaching a city, then a simple array NxN where N is the total number of cities would do the job perfectly.
- A stack with cities that you already went trough. Actually you'll use it as a LIFO object, but you'll need access to all of the object's collection. So don't want to consider
stl stack. You may use (a)
stl list instead. It would be an list of city enumerations.
- If you want to remember the longest way (the one with the most of the cities visited), you consider having another copy of the visited-cities list, for storing the result.
- Finaly, you need a recursive function that receives as a parameter a city. This function should have access (obviously) to the distances among the cities and to that "have been in the X city" stack. That access should be granted through additional parameters or should be made globally available.
Let's say you have have 3 cities:
1 2 3 4 5 6
|
enum Cities { CITY_A, CITY_B, CITY_C, NR_OF_CITIES }; //3 cities defined
int vDistances[NR_OF_CITIES][NR_OF_CITIES] = { 0, 1, 2,
1, 0, 3,
2, 3, 0};
list<Cities> beenThere;
list<Cities> finalRouteResult;
|
In some "TrackCity" recursive function, you'll have to:
- Identify the available options (that mean in our case tracking the City's row, like for
CITY_B having each
vDistances[CITY_B][n] in a loop with 'n' from
CITY_A to
CITY_C. If a distance is 0, like you said, would mean the same city, an option that you'll have to ignore.
- For each considered city, inside the tracking distances loop you'll have a second loop traking this time the stack of visited cities. If the current considered distance would be one between the current city and one already visited, ignore it. Overwise - go recursively to the new city.
- If reached a point when from the current city you can't go anywhere else, consider remembering the way in that copy of visited-cities list. That would mean taking care and do that only when the current number of visited cities is no less than the one previously remembered.
A model for the recursive function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
|
void TrackCity (Cities currentCity)
{
int nCounter;
list <Cities>::iterator it;
bool bContinueRecursively;
//register the current city in the stack
beenThere.push_front(currentCity);
for (nCounter = CITY_A; nCounter < NR_OF_CITIES; nCounter++)
{
if (vDistances[currentCity][nCouter] > 0) //check valid distance
{
bContinueRecursively = true; //the default is to go further...
for (it = beenThere.begin(); it != beenThere.end(); it++)
if (currentCity == *it)
bContinueRecursively = false; //...until proven wrong to do so
if (bContinueRecursively == true)
{
TrackCity(nCouter); //follow the white rabbit into a rabbit hole
//...which means going recursively to another city
}
else //nowhere to go, so consider remembering the path
{
if (beenThere.size() > finalRouteResult.size())
finalRouteResult = beenThere;
}
}
}
beenThere.pop_front();
}
|
These being said, I hope I've been helpful in some degree and you may have now some reference for either further study or implementation.