Summary of the Backtracking Method in leetcode: Eight queens problem; unique path problem; subsets Problem

Source: Internet
Author: User

The backtracking method uses the trial and error method to solve a problem step by step. In the process of solving the problem step by step, when it tries to find that the existing step-by-step answer cannot be effectively answered correctly, it will cancel the previous step or the previous step of operation, then try again to find the answer to the question through other possible step-by-step answers. The most classic problem is the eight queens problem.

1 n queen issues

 

N-The Queen's problem is to place the Queen's position on the board correctly, so that any two queens cannot attack each other. The attack is carried out in the same row, in the same column, or in the diagonal line.

GivenNTo return all solutions to the n-queen problem.

Each solution contains a distinct board configuration of N -Queens 'placement, where'Q' And '.' Both indicate a queen and an empty space respectively.

For example, if n is 4, the following solutions exist:

[[". Q .. ", // solution 1 "... q "," Q... ",".. q. "], ["... q. ", // solution 2" Q... ","... q ",". Q .. "]

First, we need a chessboard to save the current state, that is, the queen has been placed there, so as to judge when entering a new line. The checkerboard status can be saved using a matrix of N * n, but an array of 1 * n can also be used. The subscript of the array indicates the number of rows on the checkerboard. The value of the array is the number of columns on the checkerboard, in this way, it fully indicates which row and column can be placed as queen.AlgorithmThe structure is as follows:

1. initialize the chessboard Array

2 rows I: 1-> N

Column J: 1-> N

For each position (I, j), check whether the queen can be placed. The check principle is that the current number of columns is not equal to the number of columns of the former queen, and cannot be located on its diagonal line, note that,

If it is on the diagonal line, it must meet the following requirements: | I-row | = | j-Col |

If the queen cannot be placed, the number of columns is removed by one.

If you can put the queen, update the chessboard array and move the number of rows down one by one.

If line I does not find the place for the Queen.

If I = 0, it indicates that the first line has been traced back, all possible solutions have been found, and exit.

If I! = 0, move the Queen's position in the previous row to the back column, and then continue searching for the valid Queen's position in this row.

If the number of rows reaches the last line, it indicates that one solution has been found, backtracing, and searching for another solution.

Here we first provide a non-recursive solution:

Vector <vector <string> solvenqueens (int n) {int * A = new int [N]; // initialize for (int K = 0; k <N; k ++) A [k] =-100; Int J = 0, I = 0; vector <string> result; while (I <n) {While (j <n) {If (valid (I, j, A) {A [I] = J; j = 0; // mark break ;} else {J ++ ;}}// if row I does not find the location where the queen can be placed if (a [I] =-100) {// trace back to the first line. If no feasible solution is found, it indicates that if (I = 0) break is traversed. // if not, backtracing is performed, and clear the queen of the previous row, and move an else {-- I; j = A [I] + 1; A [I] =-100; continue ;}} // at this time, the desired queen if (I = n-1) {pushin (result, A, n) has been found ); // However, because not all combinations are returned yet, you must continue to find J = A [I] + 1; A [I] =-100; continue ;} I ++;} return result ;}

Determine whether a function is valid:

 

 

 
Bool valid (INT row, int Col, int * A) {for (INT I = 0; I <row; I ++) // The previous row in a {if (a [I] = Col | ABS (Row-I) = ABS (Col-A [I]) {return false ;}} return true ;}

Load the result:

 

 

 
Void pushin (vector <string> & result, int * a, int N) {vector <string> tmp1; For (INT I = 0; I <N; I ++) {string tmp2; For (Int J = 0; j <n; j ++) {if (a [I] = J) {tmp2 + = "Q";} else tmp2 + = ". ";} tmp1.push _ back (tmp2);} result. push_back (tmp1 );}

 

Then a recursive solution is provided:

 

 
Void Queen (INT row, int * a, int N, vector <string> & result) {If (n = row) // if the result is found, print the result pushin (result, A, n); else {for (int K = 0; k <n; k ++) {// test each column in the row if (valid (row, K, A) {A [row] = K; // place Queen (row + 1,, n, result); // continue to test the next row // re-Initialize when returning the upper level, a [row] =-100 ;}}}}

 

Vector <vector <string> solvenqueens (int n) {// start typing your C/C ++ Solution Below // do not write int main () function int * A = new int [N]; // initialize for (int K = 0; k <n; k ++) A [k] =-100; vector <vector <string> result; Queen (0, A, N, result); return result ;}

 

2 unique path of unique path

 

 

A robot is in the upper left corner of a square area of M * n. The robot can only go down or to the right. The ultimate goal of a robot is the bottom right corner. How many unique paths are possible?

Note: m and n will be at most 100.

Since each time can only go down or to the right, so the current node I, the number of paths at J should be equal to the upper node I-1, J and Its left node I, the total number of paths of the J-1.

PATH (I, j) = path (I-1, j) + path (I, J-1 );

First, a more intuitive recursive solution is provided:

 

 
Int backtrack (int r, int C, int M, int N) {If (r = M & C = N) return 1; if (r> M | C> N) return 0; return backtrack (R + 1, C, m, n) + backtrack (R, C + 1, m, n );}

 

However, recursion is inefficient because there are some repeated computations. Therefore, we need to introduce dynamic planning to save the path at each node to avoid repeated computation and improve algorithm efficiency.

 

 

 
Const int m_max = 100; const int n_max = 100; int backtrack (int r, int C, int M, int N, int mat [] [n_max + 2]) {If (r = M & C = N) return 1; if (r> M | C> N) return 0; // if no calculation is performed, or skip this operation. After both directions are calculated, add the results. If (MAT [R + 1] [c] =-1) mat [R + 1] [c] = backtrack (R + 1, C, M, N, mat); If (MAT [r] [C + 1] =-1) mat [r] [C + 1] = backtrack (R, C + 1, m, n, mat); Return mat [R + 1] [c] + mat [r] [C + 1];} int Bt (int m, int N) {int mat [m_max + 2] [n_max + 2]; for (INT I = 0; I <m_max + 2; I ++) {for (Int J = 0; j <n_max + 2; j ++) {mat [I] [J] =-1 ;}} return backtrack (1, 1, m, n, mat );}

3. Obtain all subsets.

 

 

Given the set S of a series of numbers, all possible subsets are returned:

Note:

    • The elements in the subset must be non-decreasing.
    • The result cannot contain duplicate subsets.

For example,
IfS=[1, 2, 3], A solution is:

 
[[3], [1], [2], [, 3], [], [], [], []

This problem is an extension of the (n, k) problem, that is, how many different methods are available to select k elements from the set of n elements. You just need to cycle K from 1 to n to get the answer.

For the (n, k) problem, the elements in the N set are constantly selected until the number is k, and then the backtracing starts. The elements at the end of K are removed and the next element in N is included, and so on until all possibilities are traversed. Stack is used as the backtracing tool. :
 
Void subsetsall (vector <int> & ANS, vector <int> TMP, vector <int> & S, int N, int K, int index) {If (k = 0) {If (find (ans. begin (), ans. end (), TMP) = ans. end () ans. push_back (TMP);} else if (k> 0 & index <n) {TMP. push_back (S. at (INDEX); subsetsall (ANS, TMP, S, N, K-1, index + 1); // you have found the first one and looked for the K-1 later. TMP. pop_back (); subsetsall (ANS, TMP, S, N, K, index + 1); // skip the first one and find K in the next one. }}

MasterProgram: As long as the loop is changed to a fixed K, it becomes the (n, k) problem.

Vector <vector <int> subsets (vector <int> & S) {// start typing your C/C ++ Solution Below // do not write int main () function sort (S. begin (), S. end (); int n = S. size (); vector <int> TMP; vector <int> ans; If (n = 0) {ans. push_back (TMP); Return ans;} For (INT I = 0; I <= N; I ++) {subsetsall (ANS, TMP, S, N, I, 0 );}}

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.