Sie sind auf Seite 1von 36

Backtracking

By
Riaz Ahmad
COMSATS WAH CANTT

A short list of categories

Algorithm types we will consider include:

Simple recursive algorithms


Backtracking algorithms
Divide and conquer algorithms
Dynamic programming algorithms
Greedy algorithms
Branch and bound algorithms
Brute force algorithms
Randomized algorithms

Backtracking (animation)
dead end
?
dead end

start

dead end

dead end
dead end

?
success!

Backtracking

Suppose you have to make a series of decisions,


among various choices, where

You dont have enough information to know what to


choose
Each decision leads to a new set of choices
Some sequence of choices (possibly more than one)
may be a solution to your problem

Backtracking is a methodical way of trying out


various sequences of decisions, until you find one
that works
4

Solving a maze

Given a maze, find a path from start to finish


At each intersection, you have to decide between
three or fewer choices:
Go straight
Go left
Go right
You dont have enough information to choose correctly
Each choice leads to another set of choices
One or more sequences of choices may (or may not) lead to a
solution
Many types of maze problem can be solved with backtracking

Backtracking Algorithm

Based on depth-first recursive search


Approach
1.
2.
3.

Tests whether solution has been found


If found solution, return it
Else for each choice that can be made
a)
b)
c)

4.

Make that choice


Recur
If recursion returns a solution, return it

If no choices remain, return failure

Some times called search tree

The backtracking algorithm

Backtracking is really quite simple--we explore each


node, as follows:
To explore node N:
1. If N is a goal node, return success
2. If N is a leaf node, return failure
3. For each child C of N,
3.1. Explore C
3.1.1. If C was successful, return success
4. Return failure

Backtracking Algorithm Example

Find path through maze

Start at beginning of maze


If at exit, return true
Else for each step from current location

Recursively find path


Return with first successful step
Return false if all steps fail

Consider a maze

Solving a maze
where a player has to decide how to get from room A to room B.
The player can move from room to room through the corridors provided,
but has no way of telling how many corridors a room is connected to until he
reaches that room.
the approach the player uses to solve the maze could be like this:
The player moves from room A to room 2.
From here he can move either to rooms 1 or 3. He chooses 1.
Dead End. He returns to room 2, then goes on to room 3.
He has no choice but to move to room 4.
Given a choice between rooms 5 and 6, he chooses 6.
Another choice between 7 and 8, he chooses 7.
Dead End. He returns to 6 and chooses 8.
Dead End again. He returns to 6 and sees that he has exhausted his choices.
He goes back to room 4, and chooses room 5.
He sees room B, moves to it, and solves the maze.

10

Pseudo code which implements the algorithm


We will now examine some described above.
function CheckRoom(RoomNumber)
begin
if RoomNumber has been visited, return.
for each room connected to this room
if ConnectedRoomNumber == B, the maze has been solved
else CheckRoom(ConnectedRoomNumber)
end for
end function
That's all! The algorithm takes care of rooms with Dead Ends,
rooms with multiple corridors, and anything you care to throw at
it. It has the elegant simplicity characteristic of all recursive
procedures, but it differs slightly from the functions we have
studied previously. It is a backtracking algorithm.
11

How Backtracking works

The sample maze, like all mazes, is essentially a tree, with room A at the root of the
tree.
the backtracking algorithm discussed above is a tree-spanning algorithm. When it
reaches a node like room 2, where it has more than one path to choose from, it picks
one path (to room 1) which is a leaf node, or Dead End. Finding that it can proceed no
more, it unwinds to it's previous execution, (back to room 2) and takes the other path,
to room 3. Such an algorithm is known as a depth-first spanning algorithm, because it
tends to follow a path right down to the bottom of the tree, before it gives up and
unwinds to a previous execution in order to choose a different path. Manually apply the
CheckRoom function above to the tree to get a feel of how the algorithm works.
Backtracking procedures are characterized by multiple recursive calls, typically within
a loop (see the CheckRoom function above).
a backtracking procedure goes through multiple winding and unwinding stages as it
loops through the choices it has to make at every node. One of the most common
applications of backtracking is in the evaluation of moves for strategy games like chess.
We will look at a much simpler game, tic-tac-toe, and see how a backtracking strategy
can be used to ensure that we can never lose the game.

12

How Backtracking works

The maze as a tree

13

Coloring a map

You wish to color a map with


not more than four colors

red, yellow, green, blue

Adjacent countries must be in


different colors
You dont have enough information to choose colors
Each choice leads to another set of choices
One or more sequences of choices may (or may not) lead to a
solution
Many coloring problems can be solved with backtracking

14

Backtracking Algorithm Example

Color a map with no more than four colors

If all countries have been colored return success


Else for each color c of four colors and country n

If country n is not adjacent to a country that has been colored c


Color country n with color c
Recursively color country n+1
If successful, return success

Return failure

15

Full example: Map coloring

The Four Color Theorem states that any map on a


plane can be colored with no more than four colors,
so that no two countries with a common border are
the same color
For most maps, finding a legal coloring is easy
For some maps, it can be fairly difficult to find a legal
coloring
We will develop a complete Java program to solve
this problem

16

Data structures

We need a data structure that is easy to work with,


and supports:

Setting a color for each country


For each country, finding all adjacent countries

We can do this with two arrays

An array of colors, where countryColor[i] is the


color of the ith country
A ragged array of adjacent countries, where map[i][j]
is the jth country adjacent to country i

Example: map[5][3]==8 means the 3th country adjacent to


country 5 is country 8
17

Creating the map


0

int map[][];
void createMap() {
map = new int[7][];
map[0] = new int[] {
map[1] = new int[] {
map[2] = new int[] {
map[3] = new int[] {
map[4] = new int[] {
map[5] = new int[] {
map[6] = new int[] {
}

1
4

2 3
5

1,
0,
0,
2,
0,
2,
2,

4,
4,
4,
4,
1,
6,
3,

2, 5 };
6, 5 };
3, 6, 5 };
6 };
6, 3, 2 };
1, 0 };
4, 1, 5 };
18

Setting the initial colors


static
static
static
static
static

final
final
final
final
final

int
int
int
int
int

NONE = 0;
RED = 1;
YELLOW = 2;
GREEN = 3;
BLUE = 4;

int mapColors[] = { NONE, NONE, NONE, NONE,


NONE, NONE, NONE };

19

The main program


(The name of the enclosing class is ColoredMap)
public static void main(String args[]) {
ColoredMap m = new ColoredMap();
m.createMap();
boolean result = m.explore(0, RED);
System.out.println(result);
m.printMap();
}

20

The backtracking method


boolean explore(int country, int color) {
if (country >= map.length) return true;
if (okToColor(country, color)) {
mapColors[country] = color;
for (int i = RED; i <= BLUE; i++) {
if (explore(country + 1, i)) return true;
}
}
return false;
}
21

Checking if a color can be used


boolean okToColor(int country, int color) {
for (int i = 0; i < map[country].length; i++) {
int ithAdjCountry = map[country][i];
if (mapColors[ithAdjCountry] == color) {
return false;
}
}
return true;
}

22

Printing the results


void printMap() {
for (int i = 0; i < mapColors.length; i++) {
System.out.print("map[" + i + "] is ");
switch (mapColors[i]) {
case NONE: System.out.println("none"); break;
case RED:
System.out.println("red");
break;
case YELLOW: System.out.println("yellow"); break;
case GREEN: System.out.println("green"); break;
case BLUE:
System.out.println("blue");
break;
}
}
}

23

Solving a puzzle

In this puzzle, all holes but one


are filled with white pegs
You can jump over one peg
with another
Jumped pegs are removed
The object is to remove all
but the last peg
You dont have enough information to jump correctly
Each choice leads to another set of choices
One or more sequences of choices may (or may not) lead to a
solution
Many kinds of puzzle can be solved with backtracking

24

What is searching?
If you want to go from Point A to Point B, you are employing
some kind of search. For a direction finder, going from Point A to
Point B literally means finding a path between where you are
now and your intended destination.
For a chess game, Point A to Point B might be two points
between its current position and its position 5 moves from now.
Searching falls under Artificial Intelligence (AI). A major goal of
AI is to give computers the ability to think, or in other words,
mimic human behavior. The problem is, unfortunately, computers
don't function in the same way our minds do. They require a
series of well-reasoned out steps before finding a solution. Your
goal, then, is to take a complicated task and convert it into
simpler steps that your computer can handle.

25

Search representation
First, we need a representation of how our search problem will
exist. The following is an example of our search tree

In our above graph, the path connections are not two-way. All
paths go only from top to bottom
26

Depth First Search

Depth first search works by taking a node, checking its


neighbors, expanding the first node it finds among the
neighbors, checking if that expanded node is our
destination, and if not, continue exploring more nodes.

27

Pseudo code / Informal Algorithms (Depth First Search)


Declare two empty lists: Open and Closed.
Add Start node to our Open list.
While our Open list is not empty, loop the following:

Remove the first node from our Open List.


Check to see if the removed node is our destination.

If the removed node is our destination, break out of the loop, add the
node to our Closed list, and return the value of our Closed list.
If the removed node is not our destination, continue the loop (go to Step
c).

Extract the neighbors of our above removed node.


Add the neighbors to the beginning of our Open list, and add the
removed node to our Closed list. Continue looping.

28

Steps in Depth First Search

Step 0
Let's start with our root/goal node:
I will be using two lists to keep track of what we are
doing - an Open list and a Closed List. An Open list
keeps track of what you need to do, and the Closed List
keeps track of what you have already done.
Open List: A
Closed List: <empty>

29

Step 1

Now, let's explore the neighbors of our A node. To put


another way, let's take the first item from our Open list
and explore its neighbors:
Node A's neighbors are the B and C nodes. Because we
are now done with our A node, we can remove it from
our Open list and add it to our Closed List.
You now have two new nodes B and C that need
exploring.
Add those two nodes to our Open list.
Open List: B, C
Closed List: A
30

Steps 2

Our Open list contains two items. For depth first search and
breadth first search, you always explore the first item from our
Open list. The first item in our Open list is the B node. B is not
our destination, so let's explore its neighbors:

Because I have now expanded B, I am going to remove it from


the Open list and add it to the Closed List. Our new nodes are D
and E, and we add these nodes to the beginning of our Open list:
Open List: D, E, C
Closed List: A, B

31

Step3

You should start to see a pattern forming. Because D is


at the beginning of our Open List, we expand it. D isn't
our destination, and it does not contain any neighbors.
All you do in this step is remove D from our Open List
and add it to our Closed List:
Open List: E, C
Closed List: A, B, D

32

Step 4

We now expand the E node from our Open list. E is not our destination, so we
explore its neighbors and find out that it contains the neighbors F and G.
Remember, F is our target, but we don't stop here though. Despite F being on
our path, we only end when we are about to expand our target Node - F in this
case:

Our Open list will have the E node removed and the F and G nodes added. The
removed E node will be added to our Closed List:
Open List: F, G, C
Closed List: A, B, D, E

33

Step 5

We now expand the F node. Since it is our intended destination, we stop:

We remove F from our Open list and add it to our Closed List. Since we are at
our destination, there is no need to expand F in order to find its neighbors. Our
final Open and Closed Lists contain the following data:
Open List: G, C
Closed List: A, B, D, E, F
The final path taken by our depth first search method is what the final value of
our Closed List is: A, B, D, E, F

34

Breadth First Search


Depth and Breadth first search methods are covered in
the same Lecture is because they are both similar. In
depth first search, newly explored nodes were added to
the beginning of your Open list. In breadth first search,
newly explored nodes are added to the end of your
Open list.

35

Pseudo code / Informal Algorithms ( breadth First


Search)
Declare two empty lists: Open and Closed.
Add Start node to our Open list.
While our Open list is not empty, loop the following:

Remove the first node from our Open List.


Check to see if the removed node is our destination.

If the removed node is our destination, break out of the loop, add the node to
our Closed list, and return the value of our Closed list.
If the removed node is not our destination, continue the loop (go to Step c).

Extract the neighbors of our above removed node.


Add the neighbors to the end of our Open list, and add the removed node
to our Closed list.

36

Das könnte Ihnen auch gefallen