陷入无限循环(骑士之旅问题)
Posted
技术标签:
【中文标题】陷入无限循环(骑士之旅问题)【英文标题】:Stuck in an infinite loop (Knight's Tour Problem) 【发布时间】: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;
(有效地放置所有东西)的组合在全局命名空间中的标准命名空间中)。这会污染全局命名空间,把你的代码变成一个噩梦般的标识符地雷,让你绊倒。
【参考方案1】:
这里有两个问题:
-
您正在复制 64-int 向量 every。单身的。时间。
您将 9 行打印到标准输出 每个。单身的。时间。
这两项都是极其昂贵的操作。你最多可以递归 8^64 = 2^192 次。这不是一个微不足道的数字。
如果你通过引用传递你的向量并在每个递归调用的开头杀死printBoard
...中提琴! https://ideone.com/K0DU3q
【讨论】:
以上是关于陷入无限循环(骑士之旅问题)的主要内容,如果未能解决你的问题,请参考以下文章