Backtracking is a way to traverse all possible configurations of all search spaces. These configurations may represent all permutations of an object or this is all possible methods (subsets) of the set of objects that are built. Other situations include enumerating all spanning trees of a graph, all paths of two nodes, or all the different ways to classify nodes into different colors.
One of the common difficulties with these problems is that we have to produce one possible configuration at a time. The way to avoid repeating or missing configurations is that we have to define a systematic sequence of generating configurations. We put the combinatorial search solution as a vector a= (a1,a2,..., an), and the vector element Ai comes from a finite subset of S. Such vectors may represent a sequence, and the element AI is the first element of the arrangement. Alternatively, the vector represents a subset of S,ai that represents whether the element I elements in the space is in the subset S.
At each step of the backtracking algorithm, we try to extend a given partial solution a= (A1,A2,..., AK) by adding additional elements at the end. After the expansion, we have to check that the current partial solution is not the complete solution of the condition: if so, we should output or add a number of solutions (count). If it is not a complete solution, then we should verify that the partial solution may expand into a complete solution.
The backtracking algorithm constructs a partial solution tree, each node of the tree represents a partial solution. If node y is constructed from node x, then there is an edge between x and Y. This tree provides another perspective for thinking about backtracking, and the process of structuring the solution is actually a deep-first search traversal on this tree. The structure of the backtracking algorithm is as follows:
1 BOOLfinished = FALSE;/*Do you get all the solutions?*/2BacktrackintA[],intk, data input)3 {4 intC[maxcandidates];/*the candidate for this search*/5 intNcandidates;/*Number of candidates*/6 intI/*counter*/7 if(Is_a_solution (a,k,input))8 process_solution (a,k,input);9 Else {TenK = +1; OneConstruct_candidates (a,k,input,c,&ncandidates); A for(i=0; i<ncandidates; i++) { -A[K] =C[i]; - Make_move (a,k,input); the backtrack (a,k,input); - Unmake_move (a,k,input); - if(finished)return;/*early exit if termination conditions are met*/ - } + } -}
The application portion of this algorithm consists of 5 subroutines:
1 is a solution (A,k,input)-This Boolean function verifies whether the first k elements of vector A can form a complete solution to a given problem. The last parameter, input, allows us to pass other necessary information like a function. We can use it to specify the size of the n--target solution.
2 construct candidates (a,k,input,c,ncandidates) in accordance with the current state, construct a possible selection of this step, deposited in the c[] array, whose length is deposited in ncandidates
3 process_solution (a,k,input) processing of a conforming solution, usually output, count, etc.
4 Make_move (A,k,input) and Unmake_move (A,k,input) The former will take the choice to update to the original data structure, the latter to revoke this behavior.
Find all subsets of a collection
A key question is how many objects this space needs to represent when specifying the state space that represents the combined object. For example, for a set of n elements such as the sequence {1,..., n}, how many subsets exist? When N=1, only two subsets exist, that is, {} and {1}. When n=2, there are 4 subsets that exist, with 8 subsets when n=3. So for n, there are 2n subsets present.
Each subset can be represented by whether the element is in it. To construct all 2n collections, we create a collection of n elements, where the value of AI indicates whether the first element is in a given subset. In the general backtracking algorithm mechanism, sk= (true, false) and as long as k=n A is a solution. Now we can simply implement Is_a_solution (), Construct_candidates () and Process_solution ().
Because A[k]=c[i] in each for loop, this is the only change and will be overwritten on the next iteration, without the need to specifically write Make_move () and Make_unmove ().
#include <stdio.h>#include<stdlib.h>#include<string.h>#defineMaxcandidates 100BOOLIs_a_solution (int*a,intKintN) {returnK = =N;}voidProcess_solution (intAintKintN) {inti; printf ("{"); for(i =1; I <= K; ++i) {if(A[i] = =true) printf ("%d", i); } printf ("}\n");}voidConstruct_candidate (intA[],intKintNintC[],int*ncandidates) {c[0] =false; c[1] =true; *ncandidates =2;}voidBacktrackintBintKintN) {intC[maxcandidates]; intncandidates; inti; if(Is_a_solution (A, k, n)) {process_solution (A, k, n); } Else{k= k +1; Construct_candidate (A, k, N, C,&ncandidates); for(i =0; i < ncandidates; i++) {A[k]=C[i]; Backtrack (A, k, n); } }}voidGenerate_subsets (intN) {int*a = (int*)malloc(sizeof(int)*N); Memset (A,0,sizeof(int) *N); for(inti =0; I < n; i++) A[i]= i +1; Backtrack (A,0, n);}intMain () {generate_subsets (3); return 0;}
Resources:
1. Algorithmic Design Handbook
2. Http://www.cnblogs.com/wuyuegb2312/p/3273337.html#intro
Classic algorithm Back method