【发布时间】:2019-09-24 20:41:16
【问题描述】:
骑士之旅问题: 骑士被放置在空棋盘的第一个格子上,根据国际象棋规则走棋,他必须在每个格子里走一趟。打印路径,使其覆盖所有块。
无法理解为什么代码会陷入无限循环。浪费了几个小时仍然没有头绪。 我有解决方案,但不明白为什么这个特定代码不起作用。
#include<bits/stdc++.h>
using namespace std;
#define N 8
//possible moves
int rowMove[] = {2,1,-1,-2,-2,-1,1,2};
int colMove[] = {1,2,2,1,-1,-2,-2,-1};
void printBoard(vector<vector<int>> visited)
{
for(int i=0; i<N; i++)
{
for(int j=0;j<N;j++)
cout<<visited[i][j]<<" ";
cout<<endl;
}
cout<<endl;
}
//check if the given move is valid
bool isValid(vector<vector<int>> visited,int row, int col)
{
return (row>=0 && row<N && col>=0 && col<N && visited[row][col]==0);
}
bool solveKnight(vector<vector<int>> visited,int row, int col,int move)
{
//printBoard(visited);
if(move==N*N)
{
printBoard(visited);
return true;
}
else
{
for(int i=0;i<8;i++)
{
int newRow = row + rowMove[i];
int newCol = col + colMove[i];
if(isValid(visited,newRow,newCol))
{
move++;
visited[newRow][newCol] = move;
if(solveKnight(visited,newRow,newCol,move))
return true;
move--;
visited[newRow][newCol]=0;
}
}
}
return false;
}
int main()
{
vector<vector<int>> visited(N,vector<int>(N,0));
visited[0][0]=1;
if(!solveKnight(visited,0,0,1))
cout<<"not possible";
return 0;
}
【问题讨论】:
-
您是否尝试在每个执行步骤中使用调试器单步执行代码,同时调查变量的值?
-
哎呀。在递归的每一步,您都会进行 8 次递归调用。当你的递归深度达到 8*8 = 64 级时,你就停止了。这意味着您最终会收到 8^64 = 2^192 次对
solveKnight()的调用。对我来说,它看起来不像无限循环。只是一个非常非常低效的算法。 -
没有进行全面审查,但这肯定是错误的:
vector<vector<int>> visited。你想在这里参考。 -
@scohe001 类似代码但在 2 秒内给出结果:geeksforgeeks.org/the-knights-tour-problem-backtracking-1
-
完全不相关的旁注:要非常小心
#include<bits/stdc++.h>(包括整个 C++ 标准库——你没有使用的很多 smurf)和using namespace std;(有效地放置所有东西)的组合在全局命名空间中的标准命名空间中)。这会污染全局命名空间,把你的代码变成一个噩梦般的标识符地雷,让你绊倒。
标签: c++ recursion backtracking knights-tour