【问题标题】:Chess knight tour using recursive backtracking使用递归回溯的国际象棋骑士之旅
【发布时间】:2018-08-03 17:28:33
【问题描述】:

我使用递归回溯的国际象棋骑士之旅代码不起作用。

#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时,代码用印制板编译,但结果不是完全解决的骑士之旅。

【问题讨论】:

  • 没有错误, -- 有错误(某处)为什么要这么说?
  • 我的意思是没有编译错误。
  • 我的意思是没有编译器错误。 -- 那么你看到没有编译器错误意味着你的代码没有语法错误。没有语法错误与程序是否正确运行以及没有逻辑错误无关。这就是当你需要使用调试器来调试你的代码,而不是仅仅因为你没有编译器错误而将其视为“错误”的时候。
  • 当 n 等于 62 时,代码编译——我很确定它可以编译几乎任何数字(在 INT_MIN - INT_MAX 范围内)。您的意思是当 n 等于 62 时 该程序可以工作。这两者是 非常 不同的东西...

标签: c++ recursion backtracking recursive-backtracking knights-tour


【解决方案1】:

由于moveXmoveY 数组的顺序非常对称,您的程序需要很长时间才能找到解决方案。如果您按此顺序放置组合,则以循环方式遍历方向:

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 等。棋盘顶部变得不可访问,程序浪费时间搜索所有这些肯定会失败的组合。

首先,递归回溯是一种效率低下的算法,因为可以使用大量的组合。 4x4 或 5x5 板不会遇到这些问题,因为它呈指数级扩展。但在这种情况下,我提供的答案只是“恰好”起作用。一般来说,暴力破解这种规模的东西往往需要比你有时间更多的计算。

编辑以概括/返工答案

【讨论】:

  • 我不认为这个答案一概而论。通过设置特定的搜索顺序,您基本上可以将部分解决方案提供给程序。在一般情况下,检测无法到达的单元格和回溯会更有用,或者提供有关为什么特定移动顺序更好的指导
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-30
  • 2014-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多