Run the final solution-reduction pass in both directions, since

Gareth managed to find an example (10x8#458168771440033 in r6289)
where running it in only one direction failed to eliminate an
obviously redundant piece of path.

[originally from svn r6290]
[r6289 == b25fcc3f2621b0b41f3ae7cdabe57ed07f62d2c2]
This commit is contained in:
Simon Tatham
2005-09-11 14:22:32 +00:00
parent b25fcc3f26
commit 3d3d00991a

View File

@ -1160,7 +1160,7 @@ static char *solve_game(game_state *state, game_state *currstate,
}
}
#ifdef TSP_DIAGNOSTICS
#ifndef TSP_DIAGNOSTICS
printf("before reduction, moves are ");
x = nodes[circuit[0]] / DP1 % w;
y = nodes[circuit[0]] / DP1 / w;
@ -1198,6 +1198,9 @@ static char *solve_game(game_state *state, game_state *currstate,
*/
while (1) {
int oldlen = circuitlen;
int dir;
for (dir = +1; dir >= -1; dir -= 2) {
for (i = 0; i < wh; i++)
unvisited[i] = 0;
@ -1220,31 +1223,41 @@ static char *solve_game(game_state *state, game_state *currstate,
if (i < wh)
break;
for (i = j = 0; i < circuitlen; i++) {
for (i = j = (dir > 0 ? 0 : circuitlen-1);
i < circuitlen && i >= 0;
i += dir) {
int xy = nodes[circuit[i]] / DP1;
if (currstate->grid[xy] == GEM && unvisited[xy] > 1) {
unvisited[xy]--;
} else if (currstate->grid[xy] == GEM || i == circuitlen-1) {
/*
* circuit[i] collects a gem for the only time, or is
* the last node in the circuit. Therefore it cannot be
* removed; so we now want to replace the path from
* circuit[j] to circuit[i] with a bfs-shortest path.
* circuit[i] collects a gem for the only time,
* or is the last node in the circuit.
* Therefore it cannot be removed; so we now
* want to replace the path from circuit[j] to
* circuit[i] with a bfs-shortest path.
*/
int k, dest, ni, ti, thisdist;
int p, q, k, dest, ni, ti, thisdist;
#ifdef TSP_DIAGNOSTICS
printf("optimising section from %d - %d\n", j, i);
/*
* Set up the upper and lower bounds of the
* reduced section.
*/
p = min(i, j);
q = max(i, j);
#ifndef TSP_DIAGNOSTICS
printf("optimising section from %d - %d\n", p, q);
#endif
for (k = 0; k < n; k++)
dist[k] = -1;
head = tail = 0;
dist[circuit[j]] = 0;
list[tail++] = circuit[j];
dist[circuit[p]] = 0;
list[tail++] = circuit[p];
while (head < tail && dist[circuit[i]] < 0) {
while (head < tail && dist[circuit[q]] < 0) {
int ni = list[head++];
for (k = edgei[ni]; k < edgei[ni+1]; k++) {
int ti = edges[k];
@ -1255,22 +1268,25 @@ static char *solve_game(game_state *state, game_state *currstate,
}
}
thisdist = dist[circuit[i]];
assert(thisdist >= 0 && thisdist <= i-j);
thisdist = dist[circuit[q]];
assert(thisdist >= 0 && thisdist <= q-p);
memmove(circuit+j+thisdist, circuit+i,
(circuitlen - i) * sizeof(int));
circuitlen -= i-j;
i = j + thisdist;
circuitlen += i-j;
memmove(circuit+p+thisdist, circuit+q,
(circuitlen - q) * sizeof(int));
circuitlen -= q-p;
q = p + thisdist;
circuitlen += q-p;
#ifdef TSP_DIAGNOSTICS
printf("new section runs from %d - %d\n", j, i);
if (dir > 0)
i = q; /* resume loop from the right place */
#ifndef TSP_DIAGNOSTICS
printf("new section runs from %d - %d\n", p, q);
#endif
dest = i;
dest = q;
assert(dest >= 0);
ni = circuit[i];
ni = circuit[q];
while (1) {
/* printf("dest=%d circuitlen=%d ni=%d dist[ni]=%d\n", dest, circuitlen, ni, dist[ni]); */
@ -1289,16 +1305,18 @@ static char *solve_game(game_state *state, game_state *currstate,
}
/*
* Now re-increment the visit counts for the new
* path.
* Now re-increment the visit counts for the
* new path.
*/
while (++j < i) {
int xy = nodes[circuit[j]] / DP1;
while (++p < q) {
int xy = nodes[circuit[p]] / DP1;
if (currstate->grid[xy] == GEM)
unvisited[xy]++;
}
#ifdef TSP_DIAGNOSTICS
j = i;
#ifndef TSP_DIAGNOSTICS
printf("during reduction, circuit is");
for (k = 0; k < circuitlen; k++) {
int nc = nodes[circuit[k]];
@ -1327,7 +1345,7 @@ static char *solve_game(game_state *state, game_state *currstate,
}
}
#ifdef TSP_DIAGNOSTICS
#ifndef TSP_DIAGNOSTICS
printf("after reduction, moves are ");
x = nodes[circuit[0]] / DP1 % w;
y = nodes[circuit[0]] / DP1 / w;
@ -1347,10 +1365,12 @@ static char *solve_game(game_state *state, game_state *currstate,
}
printf("\n");
#endif
}
/*
* If we've managed an entire reduction pass and not made
* the solution any shorter, we're _really_ done.
* If we've managed an entire reduction pass in each
* direction and not made the solution any shorter, we're
* _really_ done.
*/
if (circuitlen == oldlen)
break;