Backtracking | Set 1 (The Knight's tour problem) | GeeksforGeeks


Backtracking | Set 1 (The Knight's tour problem) | GeeksforGeeks
The knight is placed on the first block of an empty board and, moving according to the rules of chess, must visit each square exactly once.

Problems which are typically solved using backtracking technique have following property in common. These problems can only be solved by trying every possible configuration and each configuration is tried only once.

Backtracking works in incremental way and is an optimization over the Naive solution where all possible configurations are generated and tried.
http://www.tri.org.au/knightframe.html

Backtracking works in an incremental way to attack problems. Typically, we start from an empty solution vector and one by one add items (Meaning of item varies from problem to problem. In context of Knight’s tour problem, an item is a Knight’s move). When we add an item, we check if adding the current item violates the problem constraint, if it does then we remove the item and try other alternatives. If none of the alternatives work out then we go to previous stage and remove the item added in the previous stage. If we reach the initial stage back then we say that no solution exists. If adding an item doesn’t violate constraints then we recursively add items one by one. If the solution vector becomes complete then we print the solution.

If all squares are visited 
    print the solution
Else
   a) 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).
   b) 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.
   c) 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" )

Java code from http://www.sanfoundry.com/java-program-implement-knights-tour-problem/
private boolean isSafe(int x, int y)
{
 if (x >= 0 && x < N && y >= 0 && y < N && soln[x][y] == -1)
  return true;
 return false;
}
private boolean solveKTUtil(int x, int y, int movei, int xMove[],int yMove[])
{
 int k, next_x, next_y;
 if (movei == N * N)
  return true;
 for (k = 0; k < N; k++)
 {
  next_x = x + xMove[k];
  next_y = y + yMove[k];
  if (isSafe(next_x, next_y))
  {
   soln[next_x][next_y] = movei;
   if (solveKTUtil(next_x, next_y, movei + 1, xMove, yMove))
    return true;
   else
    soln[next_x][next_y] = -1;
  }
 }
 return false;
}

public boolean solveKnightTour()
{
 for (int x = 0; x < N; x++)
 {
  for (int y = 0; y < N; y++)
  {
   soln[x][y] = -1;
  }
 }
 int xMove[] = { 2, 1, -1, -2, -2, -1, 1, 2 };
 int yMove[] = { 1, 2, 2, 1, -1, -2, -2, -1 };
 soln[0][0] = 0;
 if (!solveKTUtil(0, 0, 1, xMove, yMove))
 {
  System.out.println("the solution does not exist");
  return false;
 }
 else
 {
  printSolution();
 }
 return true;
}
Java code: http://en.algoritmy.net/article/39907/Knights-tour
public void solve() {
066.for (int i = 0; i < ySize; i++) {
067.for (int j = 0; j < xSize; j++) {
068.takeTurn(j, i, 0);
069.solutionBoard[i][j] = NOT_VISITED; //reset the square
070.}
071.}
072.}
private void takeTurn(int x, int y, int turnNr) {
108.solutionBoard[y][x] = turnNr;
109.if (turnNr == (xSize * ySize) - 1) {
110.solutionsCount++;
111.printSolution();
112.return;
113.else {
114.for (Coords c : getFields(x, y)) {
115.if (solutionBoard[c.getY()][c.getX()] == NOT_VISITED) {
116.takeTurn(c.getX(), c.getY(), turnNr + 1);
117.solutionBoard[c.getY()][c.getX()] = NOT_VISITED; //reset the square
118.}
119.}
120.}
121.}
private List<Coords> getFields(int x, int y) {
081.List<Coords> l = new ArrayList<Coords>();
082.if (x + 2 < xSize && y - 1 >= 0)
083.l.add(new Coords(x + 2, y - 1)); //right and upward
084.if (x + 1 < xSize && y - 2 >= 0)
085.l.add(new Coords(x + 1, y - 2)); //upward and right
086.if (x - 1 >= 0 && y - 2 >= 0)
087.l.add(new Coords(x - 1, y - 2)); //upward and left
088.if (x - 2 >= 0 && y - 1 >= 0)
089.l.add(new Coords(x - 2, y - 1)); //left and upward
090.if (x - 2 >= 0 && y + 1 < ySize)
091.l.add(new Coords(x - 2, y + 1)); //left and downward
092.if (x - 1 >= 0 && y + 2 < ySize)
093.l.add(new Coords(x - 1, y + 2)); //downward and left
094.if (x + 1 < xSize && y + 2 < ySize)
095.l.add(new Coords(x + 1, y + 2)); //downward and right
096.if (x + 2 < xSize && y + 1 < ySize)
097.l.add(new Coords(x + 2, y + 1)); //right and downward
098.return l;
099.}
Also check http://rosettacode.org/wiki/Knight's_tour#Java
public class KnightsTour {
    private final static int base = 12;
    private final static int[][] moves = {{1,-2},{2,-1},{2,1},{1,2},{-1,2},
        {-2,1},{-2,-1},{-1,-2}};
    private static int[][] grid;
    private static int total;
 
    public static void main(String[] args) {
        grid = new int[base][base];
        total = (base - 4) * (base - 4);
 
        for (int r = 0; r < base; r++)
            for (int c = 0; c < base; c++)
                if (r < 2 || r > base - 3 || c < 2 || c > base - 3)
                    grid[r][c] = -1;
 
        int row = 2 + (int) (Math.random() * (base - 4));
        int col = 2 + (int) (Math.random() * (base - 4));
 
        grid[row][col] = 1;
 
        if (solve(row, col, 2))
            printResult();
        else System.out.println("no result");
 
    }
 
    private static boolean solve(int r, int c, int count) {
        if (count > total)
            return true;
 
        List<int[]> nbrs = neighbors(r, c);
 
        if (nbrs.isEmpty() && count != total)
            return false;
 
        Collections.sort(nbrs, new Comparator<int[]>() {
            public int compare(int[] a, int[] b) {
                return a[2] - b[2];
            }
        });
 
        for (int[] nb : nbrs) {
            r = nb[0];
            c = nb[1];
            grid[r][c] = count;
            if (!orphanDetected(count, r, c) && solve(r, c, count + 1))
                return true;
            grid[r][c] = 0;
        }
 
        return false;
    }
 
    private static List<int[]> neighbors(int r, int c) {
        List<int[]> nbrs = new ArrayList<>();
 
        for (int[] m : moves) {
            int x = m[0];
            int y = m[1];
            if (grid[r + y][c + x] == 0) {
                int num = countNeighbors(r + y, c + x);
                nbrs.add(new int[]{r + y, c + x, num});
            }
        }
        return nbrs;
    }
 
    private static int countNeighbors(int r, int c) {
        int num = 0;
        for (int[] m : moves)
            if (grid[r + m[1]][c + m[0]] == 0)
                num++;
        return num;
    }
 
    private static boolean orphanDetected(int cnt, int r, int c) {
        if (cnt < total - 1) {
            List<int[]> nbrs = neighbors(r, c);
            for (int[] nb : nbrs)
                if (countNeighbors(nb[0], nb[1]) == 0)
                    return true;
        }
        return false;
    }
 
    private static void printResult() {
        for (int[] row : grid) {
            for (int i : row) {
                if (i == -1) continue;
                System.out.printf("%2d ", i);
            }
            System.out.println();
        }
    }
}
Warnsdorff’s Rule
It stipulates that we move the knight such that it advances to a square which has the fewest onward moves from that particular starting location.
 The heuristic is to visit a square which has less number of non-visited neighbors. This is quite intuitive because if we have to visit all the squares in a tour, we better visit those squares which are remote  and are difficult to be reached. 
As with any heuristic, there is no mathematical proof for Warnsdoff's rule that it will always produce a valid tour.
This rule may also more generally be applied to any graph. In graph-theoretic terms, each move is made to the adjacent vertex with the least degree. Although the Hamiltonian path problem is NP-hard in general, on many graphs that occur in practice this heuristic is able to successfully locate a solution in linear time.[13] The knight's tour is a special case.

Warnsdorff’s Rule applies to boards of size 50 or less but experiences difficulty finding an tour past that point. Two improvements (W+ and W2) have been introduced as better methods that draw on the same principles as Warnsdorff’s Rule.

Additionally, in the event of a tie between two squares, various tie-breaking algorithms have been developed to address that situation.

http://www.simplecode.in/famous-problems/knights-tour/#ffs-tabbed-392

Knight’s Tours Using a Neural Network

http://mccxj.github.io/blog/20120712_horse-riding-chessboard.html
在每个结点对其子结点进行选取时,优先选择‘出口’最小的进行搜索,‘出口’的意思是在这些子结点中它们的可行子结点的个数,也就是‘孙子’结点越少的越优先跳,为什么要这样选取,这是一种局部调整最优的做法,如果优先选择出口多的子结点,那出口少的子结点就会越来越多,很可能出现‘死’结点(顾名思义就是没有出口又没有跳过的结点),这样对下面的搜索纯粹是徒劳,这样会浪费很多无用的时间,反过来如果每次都优先选择出口少的结点跳,那出口少的结点就会越来越少,这样跳成功的机会就更大一些。这种算法称为为贪心算法,也叫贪婪算法或启发示算法,它对整个求解过程的局部做最优调整,它只适用于求较优解或者部分解,而不能求最优解。这样的调整方法叫贪心策略
http://bosshida.iteye.com/blog/729854
  1. public class HorseStep {  
  2.     static final int[] dx = { -1, -2, -2, -11221 }; // x方向的增量  
  3.     static final int[] dy = { 21, -1, -2, -2, -112 }; // y方向的增量  
  4.     static final int N = 8;  
  5.     static int[][] board = new int[N][N]; // 棋盘  
  6.   
  7.     // 计算结点出口  
  8.     int waysOut(int x, int y) {  
  9.         int tx, ty;  
  10.         int count = 0;  
  11.         // 结点位置非法或已踏过,返回-1  
  12.         if (x < 0 || y < 0 || x >= N || y >= N || board[x][y] > 0) {  
  13.             return -1;  
  14.         }  
  15.         for (int i = 0; i < N; ++i) {  
  16.             tx = x + dx[i];  
  17.             ty = y + dy[i];  
  18.             if (tx < 0 || ty < 0 || tx >= N || ty >= N) {  
  19.                 continue;  
  20.             }  
  21.             if (board[tx][ty] == 0) {  
  22.                 count++;  
  23.             }  
  24.         }  
  25.         return count;  
  26.     }  
  27.   
  28.     // 按结点出口数,从小到大排序  
  29.     void sortnode(HorseNode[] hn, int n)// 采用简单排序法,因为子结点数最多只有8  
  30.     {  
  31.         int i, j, t;  
  32.         HorseNode temp;  
  33.         for (i = 0; i < n; ++i) {  
  34.             for (t = i, j = i + 1; j < n; ++j)  
  35.                 if (hn[j].waysOutNum < hn[t].waysOutNum)  
  36.                     t = j;  
  37.             if (t > i) {  
  38.                 temp = hn[i];  
  39.                 hn[i] = hn[t];  
  40.                 hn[t] = temp;  
  41.             }  
  42.         }  
  43.     }  
  44.   
  45.     // 搜索函数,count代表当前第几步  
  46.     void dfs(int x, int y, int count) {  
  47.         int i, tx, ty;  
  48.         HorseNode[] tExit = new HorseNode[N]; // 记录出口结点的出口数  
  49.   
  50.         if (count > N * N) {  
  51.             output();  
  52.             return;  
  53.         }  
  54.         // 计算[x,y]的出口结点和出口结点的出口数  
  55.         for (i = 0; i < N; i++) {  
  56.             tx = x + dx[i];  
  57.             ty = y + dy[i];  
  58.             HorseNode h = new HorseNode();  
  59.             tExit[i] = h;  
  60.             tExit[i].x = tx;  
  61.             tExit[i].y = ty;  
  62.             tExit[i].waysOutNum = waysOut(tx, ty);  
  63.         }  
  64.           
  65.         sortnode(tExit, N);  
  66.           
  67.         for(i = 0; tExit[i].waysOutNum < 0; ++i)  
  68.             ;  
  69.         for(; i < N; ++i){  
  70.             tx = tExit[i].x;  
  71.             ty = tExit[i].y;  
  72.             board[tx][ty] = count;  
  73.             dfs(tx, ty, count + 1);  
  74.             board[tx][ty] = 0;  
  75.         }  
  76.     }  
  77.       
  78.     public static void main(String[] args) {  
  79.         int x = 1;  
  80.         int y = 3;  
  81.         HorseStep test = new HorseStep();  
  82.         board[x][y] = 1;  
  83.         test.dfs(x, y, 2);  
  84.     }  
  85.   
  86.     //打印结果  
  87.     void output(){  
  88.         for(int i = N - 1; i >= 0; --i){  
  89.             for(int j = 0; j < N; ++j){  
  90.                 System.out.printf("%2d ", board[i][j]);  
  91.             }  
  92.             System.out.println();  
  93.         }  
  94.         System.exit(0);  
  95.     }  
  96.       
  97. }  
  98.   
  99. class HorseNode {  
  100.     int x;  
  101.     int y;  
  102.     int waysOutNum;  
  103. }
http://jradley.com/knightstour/
The Knight's Tour problem is ideal for multithreading. Consider that we are evaluating potential moves for a knight at a particular depth. We can kick off a separate thread to evaluate an individual jump for us. When the application is started the number of threads which are to be run by the application can be specified, else the application defaults to running on 8 threads; 

Read full article from Backtracking | Set 1 (The Knight's tour problem) | GeeksforGeeks

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts