我正在尝试为单链列表骑士的巡演问题创建回溯。我必须将链接列表实现为堆栈,并能够弹出上一个移动并使用它来回溯/尝试另一个移动。我知道程序有效,直到我必须开始回溯。我也知道列表推/弹功能正常工作。我的回溯逻辑有问题。它正在跳过一些值,或者更确切地说是尝试它们,然后在它们不起作用的情况下删除它们,但是移动数字不断上升,即使我正在递减它。我错过了逻辑上的明显错误吗?
#include "stdafx.h"
#include "Header.h"
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <iomanip>
llist list;
Move m;
int board[8][8];
int cx[] = {-2,-1, 1, 2, 2, 1, -2, -1 };
int cy[] = { 1, 2, 2, 1, -1, -2, -1, -2 };
int movenum = 1;
int backtrack = 0;
Move first;
/*Check to see if move is within the constraints of the board*/
bool constraints(int k, int b) {
if ((k < 0) || (b < 0) || (k > 7) || (b > 7) || (board[k][b] != -1)) {
return true;
}
else {
return false;
}
}
/* Initialization of 8x8 board, fill the array with -1 */
void initboard() {
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
board[x][y] = -1;
}
}
}
/* Output the current board array */
void printboard(int arr[8][8]) {
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
cout << std::setw(2) << arr[x][y] << " ";
}
cout << endl;
}
}
void updateboard(int k, int b) {
board[k][b] = movenum;
movenum++;
}
void calcmove(int x, int y, int i) {
for (i; i < 9; i++) {
int a0 = x + cx[i];
int a1 = y + cy[i];
if (constraints(a0, a1) == false) {
updateboard(a0, a1);
m.x = a0;
m.y = a1;
m.index = i;
list.push(m);
printboard(board);
backtrack = 0;
cout << "move is" << movenum << endl;
if (movenum < 64) {
return calcmove(m.x, m.y, 0);
}
else { return; }
}
}
board[m.x][m.y] = -1;
m = list.pop();
m.index = m.index + 1;
if (backtrack > 0) {
movenum--;
board[m.x][m.y] = -1;
}
cout << "move is" << movenum << "after pop" << endl;
backtrack +=1;
printboard(board);
if (movenum < 64) {
return calcmove(m.y, m.y, m.index);
}
else { return; }
}
int main()
{
int m1 = 1;
int m2 = 2; //random
first.x = m1;
first.y = m2;
first.index = 0;
list.push(first); //push first node on to stack
initboard();
updateboard(m1, m2); //update board
calcmove(first.x, first.y, 0);
printboard(board);
}
回溯发生在calcmove函数中,如果它不在板上,已经占用了空间,并且它已经检查了每个可用的移动。
答案 0 :(得分:2)
此溶胶的最坏情况复杂度为O(N^(N^2))
。在最糟糕的情况下,将检查8^64
组合。
由于这种高度复杂的代码需要花费大量时间来运行,并且很难找到这种复杂性中的错误。
calcmove
for-loop
函数中存在一个错误,该错误正在运行 9 次而不是 8 强>次。
第二个是
91
if (movenum < 64) {
return calcmove(m.y, m.y, m.index);
}
其中m.y
作为第一个参数而不是m.x
为了更好地理解回溯,这里也存在类似的问题 here