52
CSCI 104 Recursion Mark Redekopp David Kempe

CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

  • Upload
    others

  • View
    10

  • Download
    0

Embed Size (px)

Citation preview

Page 1: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

CSCI 104

Recursion

Mark Redekopp

David Kempe

Page 2: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

2© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Recursion

Problem in which the solution can be expressed in terms

of itself (usually a smaller instance/input of the same

problem) and a base/terminating case

Input to the problem must be categorized as a:

– Base case: Solution known beforehand or easily computable (no

recursion needed)

– Recursive case: Solution can be described using solutions to

smaller problems of the same type

• Keeping putting in terms of something smaller until we reach the base

case

Factorial: n! = n * (n-1) * (n-2) * … * 2 * 1

– n! = n * (n-1)!

– Base case: n = 1

– Recursive case: n > 1 => n*(n-1)!

Page 3: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

3© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Recursive Functions

Recall the system stack essentially provides separate areas of memory for each ‘instance’ of a function

Thus each local variable and actual parameter of a function has its own value within that particular function instance’s memory space

int fact(int n)

{

if(n == 1){

// base case

return 1;

}

else {

// recursive case

return = n * fact(n-1);

}

}

C Code:

Page 4: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

4© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Recursion & the Stack

Must return back through the each call int fact(int n)

{

if(n == 1){

// base case

return 1;

}

else {

// recursive case

return = n * fact(n-1);

}

}

int main()

{

int val = 4;

cout << fact(val) << endl;

}

Stack Area of RAM

main4 val0xbf8

00400120Return

link0xbfc

4 n0xbf0

004001844Return

link0xbf4

fact

3 n0xbe8

004001844Return

link0xbec

fact

2 n0xbe0

004001844Return

link0xbe4

fact

1 n0xbd8

004001844Return

link0xbdc

fact

1

2

6

24

Page 5: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

5© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Recursion

Google is in on the joke too...

Page 6: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

6© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Recursive Functions

Many loop/iteration based approaches can be defined recursively as well

int main()

{

int data[4] = {8, 6, 7, 9};

int size=4;

int sum1 = isum_it(data, size);

int sum2 = rsum_it(data, size);

}

int isum_it(int data[], int len)

{

sum = data[0];

for(int i=1; i < len; i++){

sum += data[i];

}

}

int rsum_it(int data[], int len)

{

if(len == 1)

return data[0];

else

int sum = rsum_it(data, len-1);

return sum + data[len-1];

}

C Code:

Page 7: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

7© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Recursive Call Timeline

Each instance of rsum_it has its own len argument and sum variable

Every instance of a function has its own copy of local variables

rsum_it(data,4)

int sum=

rsum_it(data,4-1)

Time

len = 4 len = 3

len = 2 len = 1rsum_it(data,3)

int sum=

rsum_it(data,3-1)rsum_it(data,2)

int sum=

rsum_it(data,2-1) rsum_it(data,1)

return data[0];

int main(){

int data[4] = {8, 6, 7, 9};

int size=4;

int sum2 = rsum_it(data, size);

...

}

8

int rsum_it(int data[], int len)

{

if(len == 1)

return data[0];

else

int sum = rsum_it(data, len-1);

return sum + data[len-1];

}

int sum = 8

return 8+data[1];int sum = 14

return 14+data[2];int sum = 21

return 21+data[3];

14

21

30

Page 8: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

8© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Code for all functions

System Stack & Recursion

The system stack makes recursion

possible by providing separate

memory storage for the local

variables of each running instance

of the function

System stack area

System

Memory(RAM)

Code for all functions

int main()

{

int data[4] = {8, 6, 7, 9};

int size=4;

int sum2 = rsum_it(data, size);

}

int rsum_it(int data[], int len)

{

if(len == 1)

return data[0];

else

int sum =

rsum_it(data, len-1);

return sum + data[len-1];

}

Data for rsum_it (data=800,

len=4, sum=??) and return link

Data for rsum_it (data=800,

len=3, sum=??) and return link

Data for rsum_it (data=800,

len=2, sum=??) and return link

Data for rsum_it (data=800,

len=1, sum=??) and return link

Data for rsum_it (data=800,

len=2, sum=8) and return link

Data for rsum_it (data=800,

len=3, sum=14) and return link

Data for rsum_it (data=800,

len=4, sum=21) and return link

Data for main (data=800, size=4,

sum1=??,sum2=??) and return link

8 6 7 9

0 1 2 3data[4]:

800

Page 9: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

9© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Head vs. Tail Recursion

Head Recursion: Recursive call is made before the real

work is performed in the function body

Tail Recursion: Some work is performed and then the

recursive call is made

void doit(int n)

{

if(n == 1) cout << "Stop";

else {

cout << "Go" << endl;

doit(n-1);

}

}

void doit(int n)

{

if(n == 1) cout << "Stop";

else {

doit(n-1);

cout << "Go" << endl;

}

}

Tail Recursion Head Recursion

Page 10: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

10© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Head vs. Tail Recursion

Head Recursion: Recursive call is made before the real

work is performed in the function body

Tail Recursion: Some work is performed and then the

recursive call is made

Void doit(int n)

{

if(n == 1) cout << "Stop";

else {

cout << "Go" << endl;

doit(n-1);

}

}

doit(3)

Go

doit(2)

Go

doit(1)

Stop

return

return

return

Void doit(int n)

{

if(n == 1) cout << "Stop";

else {

doit(n-1);

cout << "Go" << endl;

}

}

doit(3)

doit(2)

doit(1)

Stop

Go

return

return

Go

return

Go

Go

Stop

Stop

Go

Go

Tail Recursion Head Recursion

Page 11: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

11© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Head or Tail

int main()

{

int data[4] = {8, 6, 7, 9};

int size=4;

int sum2 = rsum_it(data, size);

}

int rsum_it(int data[], int len)

{

if(len == 1)

return data[0];

else

int sum =

sum_them(data, len-1);

return sum + data[len-1];

}

int main()

{

int data[4] = {1, 6, 7, 9};

int target = 3

bsearch(data,0,4,target);

}

int bsearch(int data[],

int start, int end,

int target)

{

if(end >= start)

return -1;

int mid = (start+end)/2;

if(target == data[mid])

return mid;

else if(target < data[mid])

return bsearch(data, start, mid,

target);

else

return bsearch(data, mid, end,

target);

} Head

Tail

Page 12: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

12© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Loops & Recursion

Is it better to use recursion or iteration?

– ANY problem that can be solved using recursion can also be solved

with iteration and vice versa

– Usually, a routine with a single recursive call can be implemented

just as well or better with iteration

– When multiple recursive calls are made in the definition (i.e. in a

loop), recursion often becomes much simpler

Why use recursion?

– Usually clean & elegant. Easier to read.

– Sometimes generates much simpler code than iteration would

– Sometimes iteration will be almost impossible

How do you choose?

– Iteration is usually faster and uses less memory

– However, if iteration produces a very complex solution, consider

recursion

Page 13: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

13© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Recursive Operations on Linked List

Many linked list operations can be recursively defined

Can we make a recursive iteration function to print items?

– Recursive case: Print one item then the problem becomes to print the n-1 other items.

• Notice that any 'next' pointer can be though of as a 'head' pointer to the remaining sublist

– Base case: Empty list

(i.e. Null pointer)

How could you print values in reverse order?

void print(Item* ptr)

{

if(ptr == NULL) return;

else {

cout << ptr->val << endl;

print(ptr->next);

}

}

int main()

{ Item* head;

...

print(head);

}

val next

3 0x1c0

val next

90x0

NULL

0x148head 0x148 0x1c0

main0x148 head0xbf8

00400120Return

link0xbfc

0x148 ptr0xbf0

004001844Return

link0xbf4

print

0x1c0 ptr0xbe8

004001844Return

link0xbec

print

0x0 ptr0xbe8

004001844Return

link0xbec

print

Page 14: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

14© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Recursive Copy

How could you make a copy of a linked list using recursion

struct Item {

int val;

Item* next;

Item(int v, Item* n){

val = v; next = n;

}

};

Item* copyLL(Item* head)

{

if(head == NULL) return NULL;

else {

}

}

int main()

{ Item* oldhead, *newhead;

...

newhead = copyLL(oldhead);

}

val next

3 0x1c0

val next

90x0

NULL

0x148oldhead 0x148 0x1c0

???newhead

Page 15: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

15© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Recursive Copy

How could you make a copy of a linked list using recursion

struct Item {

int val;

Item* next;

Item(int v, Item* n){

val = v; next = n;

}

};

Item* copyLL(Item* head)

{

if(head == NULL) return NULL;

else {

return new Item(head->val,

copyLL(head->next));

}

}

int main()

{ Item* oldhead, *newhead;

...

newhead = copyLL(oldhead);

}

val next

3 0x1c0

val next

90x0

NULL

0x148oldhead 0x148 0x1c0

???newhead

Page 16: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

16© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Recursive Copy

How could you make a copy of a linked list using recursion

struct Item {

int val;

Item* next;

Item(int v, Item* n){

val = v; next = n;

}

};

Item* copyLL(Item* head)

{

if(head == NULL) return NULL;

else {

return new Item(head->val,

copyLL(head->next));

}

}

int main()

{ Item* oldhead, *newhead;

...

newhead = copyLL(oldhead);

}

val next

3 0x1c0

val next

90x0

NULL

0x148oldhead

0x148 0x1c0

val next

3 _____

0x840

val next

9 _____

0x7c0

val next

3 7c0

0x840

val next

90x0

NULL

0x7c0

0x840

newhead

copyLL(0x148) copyLL(0x1c0) copyLL(0x0)

0x0

Page 17: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

17© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

BACKTRACK SEARCH

ALGORITHMS

Page 18: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

18© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Generating All Combinations

Recursion offers a simple way to generate all combinations

of N items from a set of options, S

– Example: Generate all 2-digit decimal numbers (N=2, S={0,1,…,9})

Page 19: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

19© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Recursive Backtracking Search

Recursion allows us to "easily" enumerate all solutions to some problem

Backtracking algorithms…

– Are often used to solve constraint satisfaction problem or optimization process

• Several items that can be set to 1 of N values under some constraints

– Stop searching down a path at the first indication that constraints won't lead to a

solution

Some common and important problems can be solved with backtracking

Knapsack problem

– You have a set of objects with a given weight and value. Suppose you have a

knapsack that can hold N pounds, which subset of objects can you pack that

maximizes the value.

– Example:

• Knapsack can hold 35 pounds

• Object A: 7 pounds, $12 ea. Object B: 10 pounds, $18 ea.

• Object C: 4 pounds, $7 ea. Object D: 2.4 pounds, $4 ea.

Other examples:

– Map Coloring

– Traveling Salesman Problem

– Sudoku

– N-Queens

Page 20: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

20© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

N-Queens Problem

Problem: How to place N queens

on an NxN chess board such that

no queens may attack each other

Fact: Queens can attack at any

distance vertically, horizontally, or

diagonally

Observation: Different queen in

each row and each column

Backtrack search approach:

– Place 1st queen in a viable option

then, then try to place 2nd queen, etc.

– If we reach a point where no queen

can be placed in row i or we've

exhausted all options in row i, then

we return and change row i-1

Page 21: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

21© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

8x8 Example of N-Queens

Now place 2nd queen

Page 22: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

22© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

8x8 Example of N-Queens

Now place others as viable

After this configuration here,

there are no locations in row 6

that are not under attack from the

previous 5

BACKTRACK!!!

Page 23: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

23© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

8x8 Example of N-Queens

Now place others as viable

After this configuration here,

there are no locations in row 6

that is not under attack from the

previous 5

So go back to row 5 and switch

assignment to next viable option

and progress back to row 6

Page 24: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

24© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

8x8 Example of N-Queens

Now place others as viable

After this configuration here,

there are no locations in row 6

that is not under attack from the

previous 5

Now go back to row 5 and switch

assignment to next viable option

and progress back to row 6

But still no location available so

return back to row 5

Page 25: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

25© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

8x8 Example of N-Queens

Now place others as viable

After this configuration here,

there are no locations in row 6

that is not under attack from the

previous 5

Now go back to row 5 and switch

assignment to next viable option

and progress back to row 6

But still no location available so

return back to row 5

But now no more options for row

5 so return back to row 4

BACKTRACK!!!!

Page 26: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

26© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

8x8 Example of N-Queens

Now place others as viable

After this configuration here,

there are no locations in row 6

that is not under attack from the

previous 5

Now go back to row 5 and switch

assignment to next viable option

and progress back to row 6

But still no location available so

return back to row 5

But now no more options for row

5 so return back to row 4

Move to another place in row 4

and restart row 5 exploration

Page 27: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

27© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

8x8 Example of N-Queens

Now place others as viable

After this configuration here,

there are no locations in row 6

that is not under attack from the

previous 5

Now go back to row 5 and switch

assignment to next viable option

and progress back to row 6

But still no location available so

return back to row 5

But now no more options for row

5 so return back to row 4

Move to another place in row 4

and restart row 5 exploration

Page 28: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

28© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

8x8 Example of N-Queens

Now a viable option exists for row

6

Keep going until you successfully

place row 8 in which case you

can return your solution

What if no solution exists?

Page 29: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

29© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

8x8 Example of N-Queens

Now a viable option exists for row

6

Keep going until you successfully

place row 8 in which case you

can return your solution

What if no solution exists?

– Row 1 queen would have exhausted

all her options and still not find a

solution

Page 30: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

30© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Backtracking Search

Recursion can be used to

generate all options

– 'brute force' / test all options

approach

– Test for constraint satisfaction

only at the bottom of the 'tree'

But backtrack search

attempts to 'prune' the

search space

– Rule out options at the partial

assignment level

Brute force enumeration might

test only once a possible

complete assignment is made

(i.e. all 4 queens on the board)

Page 31: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

31© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

N-Queens Solution Development

Let's develop the code

1 queen per row

– Use an array where index represents the

queen (and the row) and value is the

column

Start at row 0 and initiate the search [i.e.

search(0) ]

Base case:

– Rows range from 0 to n-1 so STOP when

row == n

– Means we found a solution

Recursive case

– Recursively try all column options for that

queen

– But haven't implemented check of viable

configuration…

int *q; // pointer to array storing

// each queens location

int n; // number of board / size

void search(int row)

{

if(row == n)

printSolution(); // solved!

else {

for(q[row]=0; q[row]<n; q[row]++){

search(row+1);

}

}

q[i] = column of queen i 2 0 3 1

0 1 2 3Index = Queen i in row i

i

0

1

2

3

Page 32: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

32© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

N-Queens Solution Development

To check whether it is safe to place a

queen in a particular column, let's keep

a "threat" 2-D array indicating the threat

level at each square on the board

– Threat level of 0 means SAFE

– When we place a queen we'll update squares that

are now under threat

– Let's name the array 't'

Dynamically allocating 2D arrays in C/C++

doesn't really work– Instead conceive of 2D array as an "array of arrays"

which boils down to a pointer to a pointer

int *q; // pointer to array storing

// each queens location

int n; // number of board / size

int **t; // thread 2D array

int main()

{

q = new int[n];

t = new int*[n];

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

t[i] = new int[n];

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

t[i][j] = 0;

}

}

search(0); // start search

// deallocate arrays

return 0;

}

q[i] = column of queen i 0

0 1 2 3Index = Queen i in row i

i

0

1

2

3

1a0

0 0 0

2c0

1b4

3e0

0

0 0 0 0

0 1 2 3

0

1

2

3

410

0 0 0 0

0 0 0 0

Each entry

is int *

Thus t is

int **

t

t[2] = 0x1b4

t[2][1]= 0x1b8

00

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

Allocated

on line 08

Each allocated

on an iteration

of line 10

0 1 1 1

1 1 0 0

1 0 1 0

1 0 0 1

Page 33: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

33© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

N-Queens Solution Development

After we place a queen in a location,

let's check that it has no threats

If it's safe then we "place" it by adding

the new threats (+1) assuming we place

it there

Now recurse to next row

If we return it means the problem was

solved, or more often, that no solution

existed given our placement so we

remove the threats (-1)

Then we iterate to try the next location

for this queen

int *q; // pointer to array storing

// each queens location

int n; // number of board / size

int **t; // n x n threat array

void search(int row)

{

if(row == n)

printSolution(); // solved!

else {

for(q[row]=0; q[row]<n; q[row]++){

// check that col: q[row] is safe

if(t[row][q[row]] == 0){

// if safe place and continue

addToThreats(row, q[row], 1);

search(row+1);

// if return, remove placement

addToThreats(row, q[row], -1);

} } }

q[i] = column of queen i 0

0 1 2 3Index = Queen i in row i

i

0

1

2

3

0 0 0 0

0 0 0 0

0 1 2 3

0 0 0 0

0 0 0 0

t

0

1

2

3

0 1 1 1

1 1 0 0

0 1 2 3

1 0 1 0

1 0 0 1

t

0

1

2

3

0 0 0 0

0 0 0 0

0 1 2 3

0 0 0 0

0 0 0 0

t

0

1

2

3

Safe to place

queen in upper left

Now add threats Upon return,

remove threat and

iterate to next option

Page 34: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

34© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

addToThreats Code

Observations

– Already a queen in every higher row so

addToThreats only needs to deal with

positions lower on the board

• Iterate row+1 to n-1

– Enumerate all locations further down in the

same column, left diagonal and right

diagonal

– Can use same code to add or remove a

threat by passing in change

Can't just use 2D true/false array as a

square might be under threat from two

places and if we remove 1 piece we want

to make sure we still maintain the threat

void addToThreats(int row, int col, int change)

{

for(int j = row+1; j < n; j++){

// go down column

t[j][col] += change;

// go down right diagonal

if( col+(j-row) < n )

t[j][col+(j-row)] += change;

// go down left diagonal

if( col-(j-row) >= 0)

t[j][col-(j-row)] += change;

}

}

q[i] = column of queen i 0

0 1 2 3Index = Queen i in row i

i

0

1

2

3

0 1 1 1

1 1 0 0

0 1 2 3

1 0 1 0

1 0 0 1

t

0

1

2

3

0 1 1 1

1 1 0 0

0 1 2 3

1 1 2 1

2 0 1 1

t

0

1

2

3

Page 35: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

35© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

N-Queens Solution

void addToThreats(int row, int col, int change)

{

for(int j = row+1; j < n; j++){

// go down column

t[j][col] += change;

// go down right diagonal

if( col+(j-row) < n )

t[j][col+(j-row)] += change;

// go down left diagonal

if( col-(j-row) >= 0)

t[j][col-(j-row)] += change;

}

}

bool search(int row)

{

if(row == n){

printSolution(); // solved!

return true;

}

else {

for(q[row]=0; q[row]<n; q[row]++){

// check that col: q[row] is safe

if(t[row][q[row]] == 0){

// if safe place and continue

addToThreats(row, q[row], 1);

bool status = search(row+1);

if(status) return true;

// if return, remove placement

addToThreats(row, q[row], -1);

}

return false;

}

}

int *q; // queen location array

int n; // number of board / size

int **t; // n x n threat array

int main()

{

q = new int[n];

t = new int*[n];

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

t[i] = new int[n];

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

t[i][j] = 0;

}

}

// do search

if( ! search(0) )

cout << "No sol!" << endl;

// deallocate arrays

return 0;

}

00

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

Page 36: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

36© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

General Backtrack Search

Approach Select an item and set it to one of its

options such that it meets current

constraints

Recursively try to set next item

If you reach a point where all items

are assigned and meet constraints,

done…return through recursion stack

with solution

If no viable value for an item exists,

backtrack to previous item and repeat

step 1

If viable options for the 1st item are

exhausted, no solution exists

bool sudoku(int **grid, int r, int c)

{

if( allSquaresComplete(grid) )

return true;

}

// iterate through all options

for(int i=1; i <= 9; i++){

grid[r][c] = i;

if( isValid(grid) ){

bool status = sudoku(...);

if(status) return true;

}

}

return false;

}

00

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

General Outline of Backtracking

Sudoku Solver

Assume r,c is current square to

set and grid is the 2D array of

values

Page 37: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

37© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

OTHER RECURSIVE

EXAMPLES

Page 38: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

38© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Towers of Hanoi Problem

Problem Statements: Move n discs from source pole to

destination pole (with help of a 3rd alternate pole)

– Cannot place a larger disc on top of a smaller disc

– Can only move one disc at a time

321

A

(src)

B

(dst)

C

(alt)

A

(src)

B

(dst)

C

(alt)

Start (n=3) Goal (n=3)

321

A B C

Not allowed

321

Page 39: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

39© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Observation 1

Observation 1: Disc 1 (smallest) can always be moved

Solve the n=2 case:A (src) B (dst) C (alt)

1

A B C

2 1

A B C

21

A B C

21

2

Move 1 from src to alt Move 2 from src to dst

Move 1 from alt to dst

Start

Page 40: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

40© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Observation 2

Observation 2: If there is only one disc on the src pole and

the dest pole can receive it the problem is trivial

3

3

A (src) B (dst) C (alt)

21

A B C

21

A B C

3

21

A B C

3

Move n-1 discs from src to alt Move disc n from src to dst

Move n-1 discs from alt to dst

21

Page 41: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

41© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Recursive solution

But to move n-1 discs from src to alt is really a smaller

version of the same problem with

– n => n-1

– src=>src

– alt =>dst

– dst=>alt

Towers(n,src,dst,alt)

– Base Case: n==1 // Observation 1: Disc 1 always movable

• Move disc 1 from src to dst

– Recursive Case: // Observation 2: Move of n-1 discs to alt & back

• Towers(n-1,src,alt,dst)

• Move disc n from src to dst

• Towers(n-1,alt,dst,src)

3

A (src) B (dst) C (alt)

21

Page 42: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

42© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Exercise

Implement the Towers of Hanoi code

– $ wget http://ee.usc.edu/~redekopp/cs104/hanoi.cpp

– Just print out "move disc=x from y to z" rather than trying to "move"

data values

• Move disc 1 from a to b

• Move disc 2 from a to c

• Move disc 1 from b to c

• Move disc 3 from a to b

• Move disc 1 from c to a

• Move disc 2 from c to b

• Move disc 1 from a to b

Page 43: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

43© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Recursive Box Diagram

Towers(3,a,b,c)

Towers(2,a,c,b)

Towers(1,a,b,c) Move D=1 a to b

Move D=2 a to c

Towers(1,b,c,a) Move D=1 b to c

Move D=3 a to b

Towers(2,c,b,a)

Towers(1,c,a,b) Move D=1 c to a

Move D=2 c to b

Towers(1,a,b,c) Move D=1 a to b

Towers(disc,src,dst,alt)

Towers Function Prototype

Page 44: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

44© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Recursive Definitions

N = Non-Negative Integers and is defined as:

– The number 0

– n + 1 where n is some non-negative integer

Palindrome (string that reads the same forward as

backwards)

– Example: dad, peep, level

– Defined as:

• Empty string

• Single character

• xPx where x is a character and P is a Palindrome

Recursive definitions are often used in defining grammars

for languages and parsers (i.e. your compiler)

Page 45: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

45© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Simple Paragraph Grammar

Substitution Rule

subject "I" | "You" | "We"

verb "run" | "walk" | "exercise" | "eat" | "play" | "sleep"

sentence subject verb '.'

sentence_list sentence

| sentence_list sentence

paragraph [TAB = \t] sentence_list [Newline = \n]

I run. You walk. We exercise.

subject verb. subject verb. subject verb.

sentence sentence sentence

sentence_list sentence sentence

sentence_list sentence

sentence_list

paragraph

Example: Example:

I eat You sleep

Subject verb subject verb

Error

Page 46: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

46© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

C++ Grammar

Rule Expansion

expr constant

| variable_id

| function_call

| assign_statement

| ‘(‘ expr ‘)’

| expr binary_op expr

| unary_op expr

expr_statement ‘;’

| expr ‘;’

assign_statement variable_id ‘=‘ expr

5 * (9 + max);

expr * ( expr + expr );

expr * ( expr );

expr * expr;

expr;

expr_statement

Example: Example: x + 9 = 5;

expr + expr = expr;

expr = expr;

NO SUBSTITUTION

Compile Error!

Page 47: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

47© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

C++ Grammar

Rule Substitution

statement expr_statement

| compound_statement

| if ( expr ) statement

| while ( expr ) statement

compound_statement ‘{‘ statement_list ‘}’

statement_list statement

| statement_list statement

while(x > 0) { doit(); x = x-2; }

while(expr) { expr; assign_statement; }

while(expr) { expr; expr; }

while(expr) { expr_statement expr_statement }

while(expr) { statement statement }

while(expr) { statement_list statement }

while(expr) { statement_list }

while(expr) compound_statement

while(expr) statement

statement

Exam

ple

: while(x > 0)

x--;

x = x + 5;

while(expr)

statement

statement

statement

statementE

xam

ple

:

Page 48: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

48© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

BACKUP

Page 49: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

49© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Combinatorics Examples

Given n things, how can you choose k of them?

– Written as C(n,k)

How do we solve the problem?

– Pick one person and single them out

• Groups that contain Joe => _______________

• Groups that don't contain Joe => _______________

– Total number of solutions: __________________

– What are base cases?

Joe

Page 50: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

50© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Combinatorics Examples

Given n things, how can you choose k of them?

– Written as C(n,k)

How do we solve the problem?

– Pick one person and single them out

• Groups that contain Joe => C(n-1, k-1)

• Groups that don't contain Joe => C(n-1, k)

– Total number of solutions: C(n-1,k-1) + C(n-1,k)

– What are base cases?

Joe

Page 51: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

51© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Combinatorics Examples

You're going to Disneyland and you're trying to pick 4

people from your dorm to go with you

Given n things, how can you choose k of them?

– Written as C(n,k)

– Analytical solution: C(n,k) = n! / [ k! * (n-k)! ]

How do we solve the problem?

Page 52: CSCI 104 Recursion - University of Southern Californiacsci104/20142/lectures/slides/L03_Recursion.pdf · Recursion allows us to "easily" enumerate all solutions to some problem Backtracking

52© Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved

Recursive Solution

Sometimes recursion can yield an incredibly simple

solution to a very complex problem

Need some base cases

– C(n,0) = 1

– C(n,n) = 1

int C(int n, int k)

{

if(k == 0 || k == n)

return 1;

else

return C(n-1,k-1) + C(n-1,k);

}