回溯功能

时间:2018-02-10 18:12:40

标签: c++ backtracking

我正在尝试为单链列表骑士的巡演问题创建回溯。我必须将链接列表实现为堆栈,并能够弹出上一个移动并使用它来回溯/尝试另一个移动。我知道程序有效,直到我必须开始回溯。我也知道列表推/弹功能正常工作。我的回溯逻辑有问题。它正在跳过一些值,或者更确切地说是尝试它们,然后在它们不起作用的情况下删除它们,但是移动数字不断上升,即使我正在递减它。我错过了逻辑上的明显错误吗?

#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函数中,如果它不在板上,已经占用了空间,并且它已经检查了每个可用的移动。

1 个答案:

答案 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