This could be solved using a "backtracking" algorithm, I think.
Try to extend the path until it is no longer possible to extend it any further (in an allowed way). Where multiple choices are possible, simply pick the first one. And when the path cannot be extended any further (with the still available domino pieces), at the current step, then go
back one step and try a
different choice at
that (previous) step. For each alternative choice, again extend the path as long as possible. If, at a certain step, all choices have been tried, then go
back one more step. Once again, try all alternative choices at
that step. And so on. If you cannot go back any more, because you already are at the "root", and already tried all choices here, then you are done. Make sure that you record the longest path(s) you were able to build at any point.
This can be implemented as a rather simple recursive function, I believe:
(pseudo-code)
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 35 36 37
|
bool solve(const Path &prefix, const std::unordered_set<DominoPiece> &remainingPieces, const size_t n)
{
if (prefix.length() >= n)
{
return true;
}
for (const auto &piece: remainingPieces)
{
if (piece.can_extend(prefix))
{
if (solve(prefix.append(piece, without(remainingPieces, piece), n))
{
return true;
}
}
const pieceTurned = piece.turn();
if (pieceTurned.can_extend(prefix))
{
if solve(prefix.append(pieceTurned, without(remainingPieces, piece), n))
{
return true;
}
}
}
return false;
}
int main(void)
{
std::unordered_set<DominoPiece> pieces
{
Piece(1, 2),
Piece(2, 10),
/* ... */
};
solve(Path.EMPTY, pieces, pieces.size());
}
|
Edit: In fact, you can also stop the search as soon as you found a path of maximum possible length, because the task only requires you to find
one such path,
not all of them.