Backtracking Is A Systematic Way of Trying Out Different Sequences of Decisions Until We Find One That
Backtracking Is A Systematic Way of Trying Out Different Sequences of Decisions Until We Find One That
The Backtracking is an algorithmic-method to solve a problem with an additional way. It uses a recursive
approach to explain the problems. We can say that the backtracking is needed to find all possible
combination to solve an optimization problem.
Backtracking is a systematic way of trying out different sequences of decisions until we find one that
"works."
o Each non-leaf node in a tree is a parent of one or more other nodes (its children)
o Each node in the tree, other than the root, has exactly one parent
Generally, however, we draw our trees downward, with the root at the top.
To "explore" node N:
Explore C
4. Return "failure"
Backtracking algorithm determines the solution by systematically searching the solution space for the given
problem. Backtracking is a depth-first search with any bounding function. All solution using backtracking
is needed to satisfy a complex set of constraints. The constraints may be explicit or implicit.
Explicit Constraint is ruled, which restrict each vector element to be chosen from the given set.
Implicit Constraint is ruled, which determine which each of the tuples in the solution space, actually satisfy
the criterion function.
N-Queen Problem.
The N Queen is the problem of placing N chess queens on an N×N chessboard so that no two queens
attack each other. For example, following is a solution for 4 Queen problem.
The expected output is a binary matrix which has 1s for the blocks where queens are placed. For example,
following is the output matrix for the above 4 queen solution.
{ 0, 1, 0, 0}
{ 0, 0, 0, 1}
{ 1, 0, 0, 0}
{ 0, 0, 1, 0}
Backtracking Algorithm: The idea is to place queens one by one in different columns, starting from the
leftmost column. When we place a queen in a column, we check for clashes with already placed queens. In
the current column, if we find a row for which there is no clash, we mark this row and column as part of
the solution. If we do not find such a row due to clashes then we backtrack and return false.
1) Start in the leftmost column
return true
3) Try all rows in the current column. Do following for every tried row.
a) If the queen can be placed safely in this row then mark this [row,
true.
3) If all rows have been tried and nothing worked, return false to trigger
backtracking.
8 Queens Problem using Backtracking
You are given an 8x8 chessboard, find a way to place 8 queens such that no queen can attack any other
queen on the chessboard. A queen can only be attacked if it lies on the same row, or same column, or the
same diagonal of any other queen. Print all the possible configurations.
To solve this problem, we will make use of the Backtracking algorithm. The backtracking algorithm, in
general checks all possible configurations and test whether the required result is obtained or not. For the
given problem, we will explore all possible positions the queens can be relatively placed at. The solution
will be correct when the number of placed queens = 8.
The time complexity of this approach is O(N!).
Input Format - the number 8, which does not need to be read, but we will take an input number for the sake
of generalization of the algorithm to an NxN chessboard.
Output Format - all matrices that constitute the possible solutions will contain the numbers 0(for empty
cell) and 1(for a cell where queen is placed). Hence, the output is a set of binary matrices.
Visualisation from a 4x4 chessboard solution :
In this configuration, we place 2 queens in the first iteration and see that checking by placing further queens
is not required as we will not get a solution in this path. Note that in this configuration, all places in the third
rows can be attacked.
As the above combination was not possible, we will go back and go for the next iteration. This means we
will change the position of the second queen.
In this, we found a solution.
Now let's take a look at the backtracking algorithm and see how it works:
The idea is to place the queens one after the other in columns, and check if previously placed queens cannot
attack the current queen we're about to place.
If we find such a row, we return true and put the row and column as part of the solution matrix. If such a
column does not exist, we return false and backtrack*
Pseudocode
START
1. begin from the leftmost column
2. if all the queens are placed,
return true/ print configuration
3. check for all rows in the current column
a) if queen placed safely, mark row and column; and
recursively check if we approach in the current
configuration, do we obtain a solution or not
b) if placing yields a solution, return true
c) if placing does not yield a solution, unmark and
try other rows
4. if all rows tried and solution not obtained, return
false and backtrack
END
Implementation
Implementaion of the above backtracking algorithm :
#include <bits/stdc++.h>
int board[8][8]; // you can pick any matrix size you want
int main(){
int n;
cin>>n; // could use a default 8 as well
placeNQueens(n);
return 0;
}
C++
Copy
0 0 1 0
1 0 0 0
0 0 0 1
0 1 0 0
main()
{
call placeNQueens(8),
placeNQueens(){
}
board[0][0] = 0 // backtrack and try for
// different configurations
}
}
}
}
C++
Copy
3. the isPossible condition is present in the loop and also calls nQueenHelper which is recursive
N-Queens Problem
N - Queens problem is to place n - queens in such a manner on an n x n chessboard that no queens attack
each other by being in the same row, column or diagonal.
It can be seen that for n =1, the problem has a trivial solution, and no solution exists for n =2 and n =3. So
first we will consider the 4 queens problem and then generate it to n - queens problem.
Given a 4 x 4 chessboard and number the rows and column of the chessboard 1 through 4.
Since, we have to place 4 queens such as q1 q2 q3 and q4 on the chessboard, such that no two queens attack
each other. In such a conditional each queen must be placed on a different row, i.e., we put queen "i" on row
"i."
Now, we place queen q1 in the very first acceptable position (1, 1). Next, we put queen q2 so that both these
queens do not attack each other. We find that if we place q2 in column 1 and 2, then the dead end is
encountered. Thus the first acceptable position for q2 in column 3, i.e. (2, 3) but then no position is left for
placing queen 'q3' safely. So we backtrack one step and place the queen 'q2' in (2, 4), the next best possible
solution. Then we obtain the position for placing 'q3' which is (3, 2). But later this position also leads to a
dead end, and no place is found where 'q4' can be placed safely. Then we have to backtrack till 'q1' and place
it to (1, 2) and then all other queens are placed safely by moving q2 to (2, 4), q3 to (3, 1) and q4 to (4, 3).
That is, we get the solution (2, 4, 1, 3). This is one possible solution for the 4-queens problem. For another
possible solution, the whole method is repeated for all partial solutions. The other solutions for 4 - queens
problems is (3, 1, 4, 2) i.e.
The implicit tree for 4 - queen problem for a solution (2, 4, 1, 3) is as follows:
Fig shows the complete state space for 4 - queens problem. But we can use backtracking method to generate
the necessary node and stop if the next node violates the rule, i.e., if two queens are attacking.
It can be seen that all the solutions to the 4 queens problem can be represented as 4 - tuples (x1, x2, x3, x4)
where xi represents the column on which queen "qi" is placed.
Place (k, i) returns a Boolean value that is true if the kth queen can be placed in column i. It tests both
whether i is distinct from all previous costs x1, x2,....xk-1 and whether there is no other queen on the same
diagonal.
1. Place (k, i)
2. {
3. For j ← 1 to k - 1
4. do if (x [j] = i)
5. or (Abs x [j]) - i) = (Abs (j - k))
6. then return false;
7. return true;
8. }
Place (k, i) return true if a queen can be placed in the kth row and ith column otherwise return is false.
x [] is a global array whose final k - 1 values have been set. Abs (r) returns the absolute value of r.
1. N - Queens (k, n)
2. {
3. For i ← 1 to n
4. do if Place (k, i) then
5. {
6. x [k] ← i;
7. if (k ==n) then
8. write (x [1....n));
9. else
10. N - Queens (k + 1, n);
11. }
12. }
Branch and bound is an algorithm design paradigm which is generally used for solving combinatorial
optimization problems. These problems are typically exponential in terms of time complexity and may require
exploring all possible permutations in worst case. The Branch and Bound Algorithm technique solves these
problems relatively quickly.
Let us consider the 0/1 Knapsack problem to understand Branch and Bound.
There are many algorithms by which the knapsack problem can be solved:
Let’s see the Branch and Bound Approach to solve the 0/1 Knapsack problem: The Backtracking Solution
can be optimized if we know a bound on best possible solution subtree rooted with every node. If the best in
subtree is worse than current best, we can simply ignore this node and its subtrees. So we compute bound (best
solution) for every node and compare the bound with current best solution before exploring the node.
Example bounds used in below diagram are, A down can give $315, B down can $275, C down can $225, D
down can $125 and E down can $30.
Given weights and values of n items, put these items in a knapsack of capacity W to get the maximum total
value in the knapsack. In other words, given two integer arrays, val[0..n-1] and wt[0..n-1] represent values
and weights associated with n items respectively. Also given an integer W which represents knapsack
capacity, find out the items such that sum of the weights of those items of a given subset is smaller than or
equal to W. You cannot break an item, either pick the complete item or don’t pick it (0-1 property).
Examples :
W = 50;
W = 60;
Output : 200
30 20 10
Approach :
Let val[] = {1, 4, 5, 7}, wt[] = {1, 3, 4, 5}
W = 7.
The 2d knapsack table will look like :
Learning reduction in general is very important. For example, if we have library functions to solve certain
problem and if we can reduce a new problem to one of the solved problems, we save a lot of time. Consider
the example of a problem where we have to find minimum product path in a given directed graph where
product of path is multiplication of weights of edges along the path. If we have code for Dijkstra’s algorithm
to find shortest path, we can take log of all weights and use Dijkstra’s algorithm to find the minimum
product path rather than writing a fresh code for this new problem.
How to prove that a given problem is NP complete?
From the definition of NP-complete, it appears impossible to prove that a problem L is NP-Complete. By
definition, it requires us to that show every problem in NP is polynomial time reducible to L. Fortunately,
there is an alternate way to prove it. The idea is to take a known NP-Complete problem and reduce it to
L. If polynomial time reduction is possible, we can prove that L is NP-Complete by transitivity of reduction
(If a NP-Complete problem is reducible to L in polynomial time, then all problems are reducible to L in
polynomial time).
What was the first problem proved as NP-Complete?
There must be some first NP-Complete problem proved by definition of NP-Complete problems. SAT
(Boolean satisfiability problem) is the first NP-Complete problem proved by Cook (See CLRS book for
proof).
It is always useful to know about NP-Completeness even for engineers. Suppose you are asked to write an
efficient algorithm to solve an extremely important problem for your company. After a lot of thinking, you
can only come up exponential time approach which is impractical. If you don’t know about NP-
Completeness, you can only say that I could not come with an efficient algorithm. If you know about NP-
Completeness and prove that the problem as NP-complete, you can proudly say that the polynomial time
solution is unlikely to exist. If there is a polynomial time solution possible, then that solution solves a big
problem of computer science many scientists have been trying for years.
We will soon be discussing more NP-Complete problems and their proof for NP-Completeness.
P Problems
P is the set of all the decision problems solvable by deterministic algorithms in polynomial time.
NP Problems
NP is the set of all the decision problems that are solvable by non - deterministic algorithms in polynomial
time.
Since deterministic algorithms are just the special case of non - deterministic ones, so we can conclude that
P is the subset of NP.
NP Hard Problem
A problem L is the NP hard if and only if satisfiability reduces to L. A problem is NP complete if and only if
L is the NP hard and L belongs to NP.
Only a decision problem can be NP complete. However, an optimization problem may be the NP hard.
Furthermore if L1 is a decision problem and L2 an optimization problem, then it is possible that L1 α L2.
One can trivially show that the knapsack decision problem reduces to knapsack optimization problem. For
the clique problem one can easily show that the clique decision problem reduces to the clique optimization
problem. In fact, one can also show that these optimization problems reduce to their corresponding decision
problems.
NP Completeness Problem
Polynomial time reductions provide a formal means for showing that one problem is at least as hard as
another, within a polynomial time factor. This means, if L1 <= L2, then L1 is not more than a polynomial
factor harder than L2. Which is why the “less than or equal to” notation for reduction is mnemonic. NP
complete are the problems whose status are unknown.
Given n cities, the distance between them and a number D, does exist a tor programme for a salesman to
visit all the cities so that the total distance travelled is at most D.
3. Satisfiability Problem:
1. L belongs to NP and
2. L' ← L for every L' belongs to NP
All NP complete problems are NP hard, but some NP hard problems are not known to be NP complete.
If NP hard problems can be solved in polynomial time, then all the NP complete problems can be solved in
polynomial time.