-1

So here is my code for the knight's tour problem, and I have been pulling my hair out trying to figure out what is wrong with it.

#include <iostream>
#include <vector>
using namespace std;
void Knights_tour(int x, int y, int move_count);
bool isSafe(int x, int y);

int m,n,start_x,start_y;
int valid_x [8] = {2,2,-2,-2,1,1,-1,-1};
int valid_y [8] = {1,-1,1,-1,2,-2,2,-2};
vector<vector<int>> board;


int main(int argc, char* argv[])
{
    m=atoi(argv[1]);
    n=atoi(argv[2]);
    start_x=atoi(argv[3]);
    start_y=atoi(argv[4]);

    board.resize(m);

    for(int i=0; i<m; i++)
        board[i].resize(n);

    Knights_tour(start_x, start_y, 1);

    for(int i=0; i<m; i++)
    {
        for(int j=0; j<n; j++)
        {
            cout<<"[  "<<board[i][j]<<"  ]";
        }
        cout << endl;
    }

    return(0);
}
void Knights_tour(int x, int y, int move_count)
{
    board[x][y]=move_count;
    if(move_count==(m*n))
    {
        cout << "Success!" << endl;
        return;
    }
    for(int i=0; i<8; i++)
    {

        if(isSafe((valid_x[i]+x), (valid_y[i]+y)))
        {
            move_count++;
            Knights_tour((valid_x[i]+x), (valid_y[i]+y), move_count);
        }
    }
}
bool isSafe(int x, int y)
{
    if(x>=0 && x<n && y>=0 && y<m && board[x][y]==0)
        return true;
    else
        return false;
}

It takes the dimensions of the board as well as the starting coordinates through the command line. For example, running "./Knight 5 5 0 0" yields a 5x5 matrix and starts at coordinate 0. Here is what that looks like

[  1  ][  18  ][  16  ][  12  ][  15  ]
[  17  ][  13  ][  13  ][  7  ][  15  ]
[  17  ][  2  ][  9  ][  4  ][  11  ]
[  14  ][  18  ][  6  ][  14  ][  8  ]
[  8  ][  16  ][  3  ][  10  ][  5  ]

As you can see it works perfectly up until 13, when it begins repeating itself. I cannot figure out why my recursive function would do this. Any help would be appreciated. Thank you

false
  • 10,264
  • 13
  • 101
  • 209
G. Petter
  • 5
  • 2
  • 1
    Can you clarify what you mean by "begins repeating itself"? – bpeikes Mar 24 '16 at 20:02
  • I suppose that is a poor way of wording it. When it reaches its 13th move in this instance, it marks 2 separate spaces as 13. There should be only one, the one that followed from the 12th move. Then it does the same for 15 and 17. & after the 14th move, it begins moving in undefined ways, like jumping over the whole grid to get to 15. – G. Petter Mar 24 '16 at 20:13

2 Answers2

1

If I understand your code correctly, you are trying to find one Knights tour of an mxn board using recursive bruteforce trying every possible solution.

The error probably happens because recursive calls not leading to a solution still modifies the board, but doesn't backtrack to clear up the modified board values. Other recursive calls then fail to find a solution since board[x][y]==0 fails.

One solution is to pass a copy of the board onto every recursive call, and then return the board at the end.

Also: using bruteforce, you can probably not expect to find a tour for much larger boards since the running time increases exponentially asymptotically.

edit: typos edit2: added possible solution

Dith
  • 151
  • 8
0

Creating a whole copy of the board on each call would use a lot of memory. I think you can avoid it by having Knights_tour return a bool which is true when a solution is found. The return value can be used when you unwind the stack to decide on if you should unset board[x][y].

if(!Knights_tour((valid_x[i]+x), (valid_y[i]+y), move_count))
{
    board[x][y] = 0;
}
bpeikes
  • 3,495
  • 9
  • 42
  • 80