1

I'm trying to create backtracking for for a singly linked list knight's tour problem. I have to implement a linked list as a stack and be able to pop the previous move and use that to back track/ try another move. I know the program works until I have to start backtracking. I also know the list push/pop functions are working properly. There's something wrong with my logic for backtracking. It's skipping some values, or rather trying them, then deleting them if they don't work, but the move number keeps going up, even though I am decrementing it. Is there an obvious error in logic I am missing?

#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);

}

The backtracking takes place in the calcmove function if it's not on the board, a space is already taken, and it has already checked every move available.

false
  • 10,264
  • 13
  • 101
  • 209
NikNik
  • 33
  • 4
  • 1
    Debugger. Use a debugger. A debugger will allow you to single step through your program watching values in variables. You may also want to draw the board as you debug, drawing new boards when recursion occurs. Often, debugging is faster than posting to StackOverflow and waiting for somebody to inspect your code or debug your code for you. – Thomas Matthews Feb 10 '18 at 18:44
  • Yes, that's what I've been doing. Checking every push and pop. But, I'm still not seeing why it's behaving that way in my logic. – NikNik Feb 10 '18 at 18:49

1 Answers1

2

The worst case complexity of this sol is O(N^(N^2)). Here in the worst case 8^64 combinations will be checked.

As such high complexity code take huge time to run and its hard to find bug in such complexity.

One bug which is there in a your calcmove function in for-loop which is running 9 times instead of 8 times.
Second one is on line 91 in

if (movenum < 64) {
        return calcmove(m.y, m.y, m.index);
    }

where m.y is passing as a first argument instead of m.x

For better understanding of backtracking here is similar problem.
here.

amar_1995
  • 575
  • 3
  • 14
  • 1
    So I would need to implement something like Warnsdorff's Algorithm for the first half or so? Using that method of backtracking seems to eliminate my need for the stack, but the nature of the exercise is that I need to use the stack. – NikNik Feb 11 '18 at 19:58
  • Warnsdorff's algorithm choose the next best position based on some heuristic. If you want to continue to use stack you have to give a track array property in `m` which will track that particular index is visited or not. – amar_1995 Feb 11 '18 at 22:15
  • wouldn't I know if it's been visited or not if it has a value? – NikNik Feb 11 '18 at 23:48
  • Which value? You could simply check visited or not visited – amar_1995 Feb 12 '18 at 04:36