Мой код тура шахматного рыцаря, использующий рекурсивное отслеживание, не работает.
#include <iostream>
using namespace std;
// goal: knight tour
#define N 8
void printArray(int board[N][N])
{
for(int i = 0; i < N; i ++)
{
for(int j = 0; j < N; j ++)
{
cout << board[i][j] << " ";
}
cout << endl;
}
}
void instArray(int board[N][N])
{
for(int i = 0; i < N; i ++)
for(int j = 0; j < N; j ++)
board[i][j] = 0;
board[0][0] = 1;
}
bool isValidMove(int posX, int posY, int moveX, int moveY, int board[N][N])
{
int finalX = posX + moveX;
int finalY = posY + moveY;
if(finalX < 0 ||
finalX > 7 ||
finalY < 0 ||
finalY > 7 ||
board[finalY][finalX] != 0)
return false;
return true;
}
bool solveKnightTour(int board[N][N], int n, int posX, int posY, int
moveX[N], int moveY[N])
{
int next_x, next_y;
if(n == 65) return true;//when n is equal to 62 the code compiles
for(int i = 0; i < 8; i ++)
{
if(isValidMove(posX, posY, moveX[i], moveY[i], board))
{
next_x = posX + moveX[i];
next_y = posY + moveY[i];
board[next_y][next_x] = n;
if(solveKnightTour(board, n + 1, next_x, next_y, moveX, moveY))
return true;
else board[next_y][next_x] = 0;
}
}
return false;
}
int main()
{
int board[N][N];
int moveX[8] = {1, 1, 2, 2, -1, -1, -2, -2};
int moveY[8] = {2, -2, 1, -1, 2, -2, 1, -1};
instArray(board);
solveKnightTour(board, 2, 0, 0, moveX, moveY);
printArray(board);
}
Там нет ошибки, но код, кажется, бесконечно зацикливается.
В функции solveKnightTour, когда n равно 62, код компилируется с печатной платой, но результат не является полностью решенным рыцарским туром.
Ваша программа занимает очень много времени, чтобы найти решение из-за очень симметричного упорядочения вашего moveX
а также moveY
массивы. Если вместо этого вы расположите комбинации в этом порядке, который будет обходить направления по кругу:
int moveX[8] = {1, 2, 2, 1, -1, -2, -2, -1};
int moveY[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
Программа найдет решение практически мгновенно.
В вашем коде, выполняя поиск «вверх 2 вправо 1» сначала, затем «вниз 2 вправо 1», второй рыцарь будет двигаться зигзагом вдоль вершины доски, от a8 до b6 до c8 до d6 и т. Д. Некоторые квадраты вдоль вершины доска становится недоступной, и программа тратит время на поиск всех этих комбинаций, которые гарантированно потерпят неудачу.
Во-первых, рекурсивный возврат — неэффективный алгоритм, который можно использовать здесь, поскольку существует огромное количество комбинаций, которые можно разыграть. Доска 4×4 или 5×5 не столкнется с этими проблемами, потому что она масштабируется экспоненциально. Но в этом случае мой предоставленный ответ только «просто случается» на работу. В общем, грубое принуждение к чему-то такого масштаба требует гораздо больше вычислений, чем у вас есть время.
Отредактировано для обобщения / переделки ответа
Других решений пока нет …