Recursion: Backtracking

32
Recursion: Backtracking Dr. Gang Qian Department of Computer Science University of Central Oklahoma

description

Recursion: Backtracking. Dr. Gang Qian Department of Computer Science University of Central Oklahoma. Objectives (Chapter 5). Understand backtracking algorithms and use them to solve problems Use recursive functions to implement backtracking algorithms - PowerPoint PPT Presentation

Transcript of Recursion: Backtracking

Page 1: Recursion: Backtracking

Recursion: Backtracking

Dr. Gang Qian

Department of Computer ScienceUniversity of Central Oklahoma

Page 2: Recursion: Backtracking

Objectives (Chapter 5)

Understand backtracking algorithms and use them to solve problems

Use recursive functions to implement backtracking algorithms

See how the choice of data structures can affect the efficiency of a program

Page 3: Recursion: Backtracking

The Eight-Queens Puzzle

How to place eight queens on a chess board so that no queen can take another Remember that in chess, a queen can take

another piece that lies on the same row, the same column or the same diagonal (either direction)

There seems to be no analytical solutions

Page 4: Recursion: Backtracking

Solutions do exists Requires luck coupled with trial and error Or much exhaustive computation

Page 5: Recursion: Backtracking

Solve the Puzzle

How will you solve the problem? Put the queens on the board one by one in some

systematic/logical order Make sure that the queen placed will not be taken

by another already on the board If you are lucky to put eight queens on the board,

one solution is found Otherwise, some queens need to be removed and

placed elsewhere to continue the search for a solution

Page 6: Recursion: Backtracking

Why put the queens in a systematic order? Make sure that you will not consider the same

situation again The whole process is suitable for recursive

programming A large problem can be divided into small

subproblems with a similar nature

Page 7: Recursion: Backtracking

An Outline of the Recursive Function Recursive function: solve_from Given a configuration of queens on the chessboard, search for all

solutions Class Queens

Represent a particular configuration of queens on the chessboard Code sketch

solve_from (Queens configuration) {if configuration already contains eight queens

Print configurationelse

for every square p that is unguarded by configuration {add a queen on square p to configuration;solve_from(configuration);remove the queen from square p of configuration;

}}

Stop Condition

Sub-problems. Need to try all possibilities

Page 8: Recursion: Backtracking

How to find the next square to try? There must be a queen, exactly one queen in

each row There can never be more than one queen in each row

Therefore, we can place the queens one row at a time in order What we have decided is actually a systematic way to

solve the problem

Page 9: Recursion: Backtracking

Example: Four Queens

X: Guarded squares ?: Other squares that have not been tried

Page 10: Recursion: Backtracking

Backtracking

Backtracking algorithms Search for a solution by

constructing partial solutions that remain consistent with the requirements of the problem, and then

extending a partial solution toward completion When inconsistency occurs, the algorithms backs

up (backtracks) by removing the most recently constructed part of the

solution, and then trying another possibility

Page 11: Recursion: Backtracking

Suitable for implementations using Recursion, or Stacks

Only the most recent part is used

Useful for situations where many possibilities may first appear, but few survive further tests Scheduling problems

Arranging sports tournaments Designing a compiler

Parsing

Page 12: Recursion: Backtracking

Main program

int main( )/* Pre: The user enters a valid board size. Post: All solutions to the n-queens puzzle for the selected board size are

printed. Uses: The class Queens and the recursive function solve_from. */{

int board_size;print_information( );cout << "What is the size of the board? " << flush;cin >> board_size;if (board size < 0 || board size > max_board)

cout << "The number must be between 0 and “ << max_board << endl;

else {Queens configuration(board_size); // Initialize empty configuration.solve_from(configuration); // Find all solutions extending

configuration.}

}

Page 13: Recursion: Backtracking

The configuration: Queens class Constructor

set the user-selected board size and initialize the empty Queens object

print print the solutions

unguarded

bool Queens :: unguarded(int col) const;Post: Returns true or false according as the square in the first

unoccupied row (row count) and column col is not guarded by any queen.

Why no row number?

Page 14: Recursion: Backtracking

insertvoid Queens :: insert(int col);Pre: The square in the first unoccupied row (row count) and column

col is not guarded by any queen.Post: A queen has been inserted into the square at row count and

column col; row count has been incremented by 1. remove

void Queens :: remove(int col);Pre: There is a queen in the square in row count - 1 and column col.Post: The above queen has been removed; count has been

decremented by 1. is_solved

bool Queens :: is_solved( ) const;Post: The function returns true if the number of queens already

placed equals board size; otherwise, it returns false.

Page 15: Recursion: Backtracking

The backtracking function: solve_from

void solve_from(Queens &configuration)/* Pre: The Queens configuration represents a partially completed

arrangement of non-attacking queens on a chessboard. Post: All n-queens solutions that extend the given configuration

are printed. The configuration is restored to its initial state. Uses: The class Queens and the function solve_from ,

recursively. */{

if (configuration.is_solved( )) configuration.print( );else

for (int col = 0; col < configuration.board_size; col++) if (configuration.unguarded(col)) { configuration.insert(col); solve_from(configuration); // Recursively continue to

add queens. configuration.remove(col); }

}

Page 16: Recursion: Backtracking

Implementation of the Queens Class Store the chessboard as a 2-dimensional array with entries

indicating the locations of the queens Queens class

const int max_board = 30;class Queens {

public:Queens(int size);bool is_solved( ) const;void print( ) const;bool unguarded(int col) const;void insert(int col);void remove(int col);int board_size; // dimension of board = maximum number

of queensprivate:

int count; // current number of queens = first unoccupied row

bool queen_square[max_board][max_board];};

Page 17: Recursion: Backtracking

Constructor

Queens :: Queens(int size)/* Post: The Queens object is set up as an empty configuration on a

chessboard with size squares in each row and column. */{

board_size = size;count = 0;for (int row = 0; row < board_size; row++)

for (int col = 0; col < board_size; col++) queen_square[row][col] = false;

}

insert

void Queens :: insert(int col)/* Pre: The square in the first unoccupied row (row count ) and

column col is not guarded by any queen.Post: A queen has been inserted into the square at row count and

column col ; count has been incremented by 1. */{ queen_square[count++][col] = true; }

is_solved, remove and print are also trivial

Page 18: Recursion: Backtracking

unguarded

bool Queens :: unguarded(int col) const/* Post: Returns true or false according as the square in the first

unoccupied row (row count ) and column col is not guarded by any queen. */

{int i;bool ok = true; // turns false if there is a queen in column or diagonalfor (i = 0; ok && i < count; i++)

// Check upper part of columnok = !queen_square[i][col];

for (i = 1; ok && count - i >= 0 && col - i >= 0; i++) // Check upper-left diagonal

ok = !queen_square[count - i][col - i]; for (i = 1; ok && count - i >= 0 && col + i < board size; i++)

// Check upper-right diagonalok = !queen_square[count - i][col + i];

return ok;}

Page 19: Recursion: Backtracking
Page 20: Recursion: Backtracking

Exercise Describe a rectangular maze by indicating its

paths and walls within an array. Write a backtracking program to find a way through the maze

You are a tournament director and need to arrange a round robin tournament among N = 2k players. In this tournament, everyone plays exactly one game each day; after N - 1 days, a match occurred between every pair of players. Write a backtracking program to do this.

Page 21: Recursion: Backtracking

Review and Refinement

The time increases rapidly with the board size First refinement

Use the 2-dimensional array to keep track of all the squares that are guarded by queens

For each square, keep a count of the number of queens guarding the square

Faster, but we still need the loops to update the guard counts for each square

Page 22: Recursion: Backtracking

Second refinement Objective

Eliminate all loops Key idea

Each row, column and diagonal can contain at most one queen

Keep track of unguarded squares by using three bool arrays: col_free, upward_free and downward_free Diagonals from the lower left to the upper right are called

upward diagonals Diagonals from the upper left to the lower right are called

downward diagonals An integer array is used to record the column

number for the queens in each row

Page 23: Recursion: Backtracking

Eliminate loops It is trivial to identify each column How to identify each diagonal

For upward diagonals, the row and column indices have a constant sum The sum ranges from 0 to 2 board_size – 2 The sum can be used to identify each upward diagonals The square in row i and column j is in upward diagonal

number i + j For downward diagonals, the difference of the row and

column indices is constant The difference ranges from -board_size+1 to board_size–1 The downward diagonal can be numbered using the

difference The square in row i and column j is in downward diagonal

number i - j + board_size - 1

Page 24: Recursion: Backtracking
Page 25: Recursion: Backtracking

Revised Queens classclass Queens {

public:Queens(int size);bool is_solved( ) const;void print( ) const;bool unguarded(int col) const;void insert(int col);void remove(int col);int board_size;

private:int count;bool col_free[max_board];bool upward_free[2 * max_board - 1];bool downward_free[2 * max_board - 1];

// column number of queen in each row int queen_in_row[max_board]; };

Refined Implementation

Page 26: Recursion: Backtracking

Constructor

Queens :: Queens(int size)/* Post: The Queens object is set up as an empty configuration on a

chessboard with size squares in each row and column. */{

board_size = size;count = 0;for (int i = 0; i < board_size; i++)

col_free[i] = true;for (int j = 0; j < (2 * board size - 1); j++)

upward_free[j] = true;for (int k = 0; k < (2 * board size - 1); k++)

downward_free[k] = true;}

Page 27: Recursion: Backtracking

Insertion

void Queens :: insert(int col)

/* Pre: The square in the first unoccupied row (row count ) and column col is not guarded by any queen.

Post: A queen has been inserted into the square at row count and column col; count has been incremented by 1. */

{

queen_in_row[count] = col;

col_free[col] = false;

upward_free[count + col] = false;

downward_free[count - col + board_size - 1] = false;

count++;

}

Page 28: Recursion: Backtracking

Unguarded

bool Queens :: unguarded(int col) const

/* Post: Returns true or false according as the square in the first unoccupied row (row count ) and column col is not guarded by any queen. */

{

return col_free[col] && upward_free[count + col]

&& downward_free[count - col + board_size - 1];

}

Page 29: Recursion: Backtracking

2-D array Implementation

New Implementation

Evaluation

Page 30: Recursion: Backtracking

Analysis of Backtracking

Effectiveness of Backtracking Naïve approach

Consider all configurations: put all 8 queens on the board and reject illegal configurations

There can be only one queen in each row 88 = 16,777,216

There can be only one queen in each column 8! = 40,320

Our program is even better, since it rejects squares in guarded diagonals

368,165,426,48

64

Page 31: Recursion: Backtracking

Part of the recursion tree for the eight-queens problem

Page 32: Recursion: Backtracking

Lower Bounds For n-queens problem, the amount of work done by

backtracking problem still grows very fast To place a queen in each of the first n/4 rows, backtracking

algorithm investigates a minimum of n(n - 3)(n - 6) … (n – 3 * n/4) positions n (n - 3) (n - 6) … (n – 3 * n / 4) > ( n / 4) (n/4)

Exponential growth

Number of solutions Not bounded by any polynomial in n Even not bounded by any exponential form kn, where k is a

constant It is proved to be an unsolved problem