1

I've tried writing a code for knight's tour problem using backtracking. My code is working for 4x4 matrix, but for 8x8 matrix it is not displaying anything on the output screen.

I don't know what am I doing wrong.

This is how my code works:

If all squares are visited

print the solution

else

  • Add one of the next moves to solution vector and recursively check if this move leads to a solution. (A Knight can make maximum eight moves. We choose one of the 8 moves in this step).

  • If the move chosen in the above step doesn't lead to a solution then remove this move from the solution vector and try other alternative moves.

  • If none of the alternatives work then return false (Returning false will remove the previously added item in recursion and if false is returned by the initial call of recursion then "no solution exists")

Here is the code that I wrote:

#include<iostream>
using namespace std;
#define n 8
int safe(int c[n][n],int i, int j)
{
    if((i>=0&&i<n)&&(j>=0&&j<n))
    {
     if(c[i][j])
      return 0;
     else 
      return 1;
    }
    return 0;
}

    int knightstour(int c[n][n],int i,int j,int k)
  {
      if(k==n*n)
     {
      for(i=0;i<n;i++)
      {
          for(j=0;j<n;j++)
             cout<<c[i][j]<<"  ";
           cout<<endl;     
       }
       return 1;
      }
     else
     {
       c[i][j]=k;
          if(safe(c,i+2,j+1))
          {
              if(knightstour(c,i+2,j+1,k+1))
                return 1;
          }

          if(safe(c,i+2,j-1))
          {
              if(knightstour(c,i+2,j-1,k+1))
                return 1;
          }

          if(safe(c,i-2,j+1))
          {
              if(knightstour(c,i-2,j+1,k+1))
                return 1;
          }

          if(safe(c,i-2,j-1))
          {
              if(knightstour(c,i-2,j-1,k+1))
                return 1;
          }

          if(safe(c,i+1,j+2))
          {
           if(knightstour(c,i+1,j+2,k+1))
             return 1;
           }

          if(safe(c,i-1,j+2))
          {
           if(knightstour(c,i-1,j+2,k+1))
             return 1;
          }

          if(safe(c,i+1,j-2))
          {
           if(knightstour(c,i+1,j-2,k+1))
             return 1;
          }

          if(safe(c,i-1,j-2))
          {
           if(knightstour(c,i-1,j-2,k+1))
             return 1;
          }

        c[i][j]=0;
        return 0;
      }
   }
  int main()
 {
   int c[n][n]={0};
   if(!knightstour(c,0,0,0))
   cout<<"solution doesn't exist";
   return 1;
 }
false
  • 10,264
  • 13
  • 101
  • 209

1 Answers1

3

Let's assume for the time being that your algorithm is correct since it appears to produce something useful for at least n == 6:

 0  13  20  23  34  11  
21  30  35  12  19  24  
14   1  22  31  10  33  
29   4   7  16  25  18  
 6  15   2  27  32   9  
 3  28   5   8  17  26  

Here are the clock time results for running your code with various values of n:

===== 1  0m  0.001s
===== 2  0m  0.001s
===== 3  0m  0.003s
===== 4  0m  0.002s
===== 5  0m  0.070s
===== 6  0m 35.997s
===== 7  ...

You'll notice I don't yet have the figure for n = 7 in there, it's still going, at 5.5 hours and counting :-)

Since it will be going for at least that long (some 330 minutes), we can probably calculate a minimal figure for size 8 using regression analysis (with a quadratic polynomial using just the data for sizes 5, 6 and as yet incomplete 7)(a). Based on those calculations, that minimal figure would be about 16.5 hours.

However, even if it's not quadratic, the fact that it jumps to 36 seconds for a 6x6 board and to (at least) 5.5 hours for 7x7 means that the algorithm you are using just does not scale well. So what you'll probably find is that it is working, you may just have to wait a while. Possibly a long while :-)


(a) In case you're interested (or want to check/critique my methods), this was my analysis. Warning: math ahead ...

We have the data set:

x (value of n)   y (seconds taken)
--------------   -----------------
      5                 0.07
      6                36.00
      7               600.00 (when it had been running ten minutes)

Using the formula:

y = ax^2 + bx + c

We end up with the simultaneous equations:

  0.07 = 25a + 5b + c (1)
 36    = 36a + 6b + c (2)
600    = 49a + 7b + c (3)

Subtracting pairs gives us:

(2) - (1):  35.93 = 11a + b (4)
(3) - (2): 564    = 13a + b (5)

(5) - (4): 528.07 = 2a

So a = 264.035. Substituting that back in to (5) gives us b = -2868.455 and substituting a and b into (3) gives us c = 7741.47. Putting those three values into equations (1), (2) and (3) gives us the expected values.

That's the method used (from my high school days) but, of course, it can be better done with a quick and dirty Python program that works quicly when the 600 figure changes:

import sys

y5 = 0.07 ; y6 = 36 ; y7 = int(sys.argv[1]) * 60

a = ((y7 - y6) - (y6 - y5)) / 2
b = (y7 - y6) - 13 * a
c = y7 - 49 * a - 7 * b

y8 = 64 * a + 8 * b + c
print(y8, y8 / 3600)

You can just run that, providing the current value for size 7 and it will push out the minimal figure (in seconds and hours).

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 1
    The pattern is obviously not quadratic. (It has a minimum when x=-b/2a near 5.432?) Recursive algorithms tend to take exponential time, which is more like your data. – aschepler Aug 30 '18 at 02:33
  • @aschepler, yes, that was just an initial calculation. Have changed the text to show that it may not be what the actual formula is. Regardless of that, the large jump at 6x6 and *massive* jump at 7x7 means that 8x8 may well not be finished before the heat death of the universe :-) – paxdiablo Aug 30 '18 at 05:36