Top Banner
Backtracking Backtracking Introduction to Backtracking
20

Backtracking

Jan 03, 2016

Download

Documents

Gabriel Valdez

Backtracking. Introduction to Backtracking. Backtracking. Junction. Backtracking is a technique used to solve problems with a large search space, by systematically trying and eliminating possibilities. A standard example of backtracking would be going through a maze. - PowerPoint PPT Presentation
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Backtracking

BacktrackingBacktrackingIntroduction to Backtracking

Page 2: Backtracking

BacktrackingBacktrackingBacktracking is a

technique used to solve problems with a large search space, by systematically trying and eliminating possibilities.

A standard example of backtracking would be going through a maze. ◦ At some point in a

maze, you might have two options of which direction to go:

Junction

Portion A

Po

rtio

n B

Page 3: Backtracking

BacktrackingBacktracking

Junction

Portion B

Po

rtio

n A

One strategy would be to try going through Portion A of the maze. If you get stuck before

you find your way out, then you "backtrack" to the junction.

At this point in time you

know that Portion A will NOT lead you out of the maze, so you then start

searching in Portion B

Page 4: Backtracking

BacktrackingBacktrackingClearly, at a single

junction you could have even more than 2 choices.

The backtracking strategy says to try each choice, one after the other, ◦ if you ever get stuck, "backtrack" to the junction and try the next choice.

If you try all choices and never found a way out, then there IS no solution to the maze.

Junctio

n

BC

A

Page 5: Backtracking

Backtracking – Eight Queens Backtracking – Eight Queens ProblemProblemFind an arrangement of

8 queens on a single chess board such that no two queens are attacking one another.

In chess, queens can move all the way down any row, column or diagonal (so long as no pieces are in the way).

◦ Due to the first two restrictions, it's clear that each row and column of the board will have exactly one queen.

Page 6: Backtracking

The backtracking strategy is as follows:1) Place a queen on the first

available square in row 1.

2) Move onto the next row, placing a queen on the first available square there (that doesn't conflict with the previously placed queens).

3) Continue in this fashion until either:

a) you have solved the problem, or

b) you get stuck. When you get stuck, remove

the queens that got you there, until you get to a row where there is another valid square to try.

Backtracking – Eight Queens Backtracking – Eight Queens ProblemProblem

Animated Example:http://www.hbmeyer.de/backtrack/achtdamen/eight.htm#up

QQ

QQ

Q Q

Continue…

Page 7: Backtracking

Backtracking – Eight Queens Backtracking – Eight Queens ProblemProblemWhen we carry out backtracking,

an easy way to visualize what is going on is a tree that shows all the different possibilities that have been tried.

Page 8: Backtracking

Backtracking – Eight Queens Backtracking – Eight Queens ProblemProblem

The neat thing about coding up backtracking, is that it can be done recursively, without having to do all the bookkeeping at once.◦Instead, the stack or recursive calls

does most of the bookkeeping ◦(ie, keeping track of which queens

we've placed, and which combinations we've tried so far, etc.)

Page 9: Backtracking

void solveItRec(int perm[], int location, struct onesquare usedList[]) {

if (location == SIZE) { printSol(perm); } for (int i=0; i<SIZE; i++) {

if (usedList[i] == false) {

if (!conflict(perm, location, i)) { perm[location] = i; usedList[i] = true; solveItRec(perm, location+1, usedList); usedList[i] = false; } } } }

perm[] - stores a valid permutation of queens from index 0 to location-1. location – the column we are placing the next queenusedList[] – keeps track of the rows in which the queens have already been placed.

Found a solution to the problem, so print it!

Loop through possible rows to place this queen.

Only try this row if it hasn’t been used

Check if this position conflicts with any previous queens on the diagonal

1) mark the queen in this row2) mark the row as used3) solve the next column location

recursively4) un-mark the row as used, so

we can get ALL possible valid solutions.

Page 10: Backtracking

Backtracking – 8 queens problem - Backtracking – 8 queens problem - AnalysisAnalysis

Another possible brute-force algorithm is generate the permutations of the numbers 1 through 8 (of which there are 8! = 40,320), ◦ and uses the elements of each permutation as indices to place

a queen on each row. ◦ Then it rejects those boards with diagonal attacking positions.

The backtracking algorithm, is a slight improvement on the permutation method, ◦ constructs the search tree by considering one row of the board

at a time, eliminating most non-solution board positions at a very early stage in their construction.

◦ Because it rejects row and diagonal attacks even on incomplete boards, it examines only 15,720 possible queen placements.

A further improvement which examines only 5,508 possible queen placements is to combine the permutation based method with the early pruning method: ◦ The permutations are generated depth-first, and the search

space is pruned if the partial permutation produces a diagonal attack

Page 11: Backtracking

Magic Number SquaresMagic Number SquaresA 3x3 magic number square has 9

numbers {1,2,… 9} that must be arranged in such a way that every row, column, and diagonal has the same sum.◦For a 3x3 magic number square the sum

is 3*(3*3+1)/2 = 15.

1515

Page 12: Backtracking

Magic Number SquareMagic Number SquareIt is possible to have different sized

magic number squares of size nxn, ◦where numbers {1,2,… n*n} must be

arranged in such a way that every row and column has the same sum.

◦For a nxn magic number square the sum is n*(n*n+1)/2

Page 13: Backtracking

Magic Number SquareMagic Number SquareSay we want to create a class

MagicSquare that takes in an int n and returns all valid Magic Number Squares of size nxn.◦Example, n = 3 returns 8 magic

squares:2 7 69 5 14 3 8

4 9 23 5 78 1 6

2 9 47 5 36 1 8

4 3 89 5 12 7 6

6 7 21 5 98 3 4

6 1 87 5 32 9 4

8 1 63 5 74 9 2

8 3 41 5 96 7 2

Page 14: Backtracking

Magic Number SquareMagic Number SquareHow would we start?

◦The plan like we did with Eight Queens is just to try a number in the first position. Then we can recursively solve the board at

the next position given that the number has been placed.

Then we systematically “throw out” boards that do not meet our constraints.

◦What do we need to do that? First we will want an empty board that we will

fill in one square at a time. Then we will want to mark which numbers in

the set (1, … , n*n) have already been used. We need to calculate the sum that each row,

column, and diagonal must add up to.

Page 15: Backtracking

public class MagicSquare {

private int[][] square;

private boolean[] possible;

private int totalSqs;

private int sum;

private int numsquares;

// Creates an empty MagicSquare object.

public MagicSquare(int n) {

// Fill in an empty square; 0 represents unfilled.

square = new int[n][n];

for (int i=0; i<n; i++)

for (int j=0; j<n; j++)

square[i][j] = 0;

// Start with all numbers being possible.

totalSqs = n*n;

possible = new boolean[totalSqs];

for (int i=0; i<totalSqs; i++)

possible[i] = true;

sum = n*(n*n+1)/2;

numsquares = 0;

}

• square[][] will hold the numbers we place.• possible[] will hold the numbers that have still not bee used yet.• sum will store what value the rows/columns/diagonals must sum to.

square[][] is size nxninitialize all values to 0, it’s empty to start!

There are n*n total numbers,so possible[] is size n*n. At first all of the numbers can be usedso the entire array is set to true.

Page 16: Backtracking

// Recursive method which fills in the square at (row,col).

public void fill(int row, int col) {

// Screen away incorrect squares.

if (!checkRows() || !checkCols() || !checkDiags())

return;

// Filled everything, so print !!

if (row == square.length) {

System.out.println(this);

numsquares++;

return;

}

// Try each possible number for this square.

for (int i=0; i<totalSqs; i++) {

if (possible[i]) {

square[row][col] = i+1;

possible[i] = false;

// Go to the next square.

int newcol = col+1;

int newrow = row;

if (newcol == square.length) {

newrow++;

newcol = 0;

}

// Recursively fill.

fill(newrow, newcol);

// Undo this square.

square[row][col] = 0;

possible[i] = true;

}

}

}

Base Cases:Either we broke the constraints, so we throw that board out.OR We’re DONE!!

Try all possible values for this spot

Find the new row and col, so we can recursively fill the next spot.

Recursively call fill() on our new spot.

Undo this square for future recursive calls, so that we can try ALL valid boards

Page 17: Backtracking

// Recursive method which fills in the square at (row,col).

public void fill(int row, int col) {

// Screen away incorrect squares.

if (!checkRows() || !checkCols() || !checkDiags())

return;

// Filled everything, so print !!

if (row == square.length) {

System.out.println(this);

numsquares++;

return;

}

// Try each possible number for this square.

for (int i=0; i<totalSqs; i++) {

if (possible[i]) {

square[row][col] = i+1;

possible[i] = false;

// Go to the next square.

int newcol = col+1;

int newrow = row;

if (newcol == square.length) {

newrow++;

newcol = 0;

}

// Recursively fill.

fill(newrow, newcol);

// Undo this square.

square[row][col] = 0;

possible[i] = true;

}

}

}

Page 18: Backtracking

// Returns true iff all the rows are okay.

public boolean checkRows() {

// Try each row.

for (int i=0; i<square.length; i++) {

int test = 0;

boolean unFilled = false;

// Add up the values in this row.

for (int j=0; j<square[i].length; j++) {

test += square[i][j];

if (square[i][j] == 0)

unFilled = true;

}

// If the row is filled and adds up to the wrong number,

// this is an invalid square.

if (!unFilled && test != sum)

return false;

}

// Never found proof of an invalid row.

return true;

}

Determine whether each row is filled andthe row’s sum.

If the row is filled and adds up to the wrong numberthen our row constraint is violated, and we return false.

At this point we have checked all rows, and none of them violated our constraint.

Page 19: Backtracking

Mazes and BacktrackingMazes and BacktrackingA final example of something that can be

solved using backtracking is a maze. ◦ From your start point, you will iterate through

each possible starting move. ◦ From there, you recursively move forward. ◦ If you ever get stuck, the recursion takes you

back to where you were, and you try the next possible move.

In dealing with a maze, to make sure you don't try too many possibilities, ◦ one should mark which locations in the maze

have been visited already so that no location in the maze gets visited twice.

◦ (If a place has already been visited, there is no point in trying to reach the end of the maze from there again.

Page 20: Backtracking

ReferencesReferencesSlides adapted from Arup Guha’s

Computer Science II Lecture notes: http://www.cs.ucf.edu/~dmarino/ucf/cop3503/lectures/

Additional material from the textbook:Data Structures and Algorithm Analysis in

Java (Second Edition) by Mark Allen WeissAdditional images:

www.wikipedia.comxkcd.com