Data Structures for Java Data Structures for Java
William H. Ford William H. Ford William R. Topp William R. Topp
Chapter 29 Chapter 29
Assorted Algorithms Assorted Algorithms
Bret Ford
Building Combinations Building Combinations
The function C(n, k) evaluates the number The function C(n, k) evaluates the number of different combinations of n items taken k of different combinations of n items taken k
at a time. Mathematics provides a definition at a time. Mathematics provides a definition
of the function in terms of factorials.
of the function in terms of factorials.
C(n,k) can be computed using a recursive C(n,k) can be computed using a recursive function
function
k!
k)!
(n n!
k)
C(n,
Building Combinations Building Combinations
(continued) (continued)
In general, we can evaluate C(n,k) by In general, we can evaluate C(n,k) by
adding the total of ways to select k items adding the total of ways to select k items
from n-1 (C(n-1,k)) and the total number from n-1 (C(n-1,k)) and the total number
in of ways to select k-1 items from n-1 in of ways to select k-1 items from n-1
items (C(n-1, k-1), assuming item n is items (C(n-1, k-1), assuming item n is
added to each combination. This defines added to each combination. This defines
the recursive step for C(n,k).
the recursive step for C(n,k).
C(n,k) = C(n-1, k) + C(n-1, k-1); // recursive step
Building Combinations Building Combinations
(concluded) (concluded)
If k = n, there is only 1 possible If k = n, there is only 1 possible
combination, namely the one with all n combination, namely the one with all n
items. Having k = 1 is the other extreme, items. Having k = 1 is the other extreme,
and each of the n singleton collections and each of the n singleton collections
consisting of one of the n items is a valid consisting of one of the n items is a valid
combination. We allow k = 0 and define combination. We allow k = 0 and define
C(n,0) to be 1.
C(n,0) to be 1.
n k or 0 k
1,
comm() comm()
public static int comm(int n, int k) {
// stopping condition if (n == k || k == 0) return 1;
else if (k == 1)
// stopping condition return n;
else
// recursive step
return comm(n-1,k) + comm(n-1,k-1);
}
Finding All Subsets Finding All Subsets
The The power set power set of an n element set S is the of an n element set S is the ‑ ‑ set of all subsets of S. The size of the
set of all subsets of S. The size of the power set is 2
power set is 2
nn. .
Finding All Subsets (continued) Finding All Subsets (continued)
Start with set S of size n. Remove one Start with set S of size n. Remove one
of the elements, x, from the set to create a new of the elements, x, from the set to create a new
set S' with n 1 elements. ‑ set S' with n 1 elements. ‑
The new set, S', has the form S' = S {x}. The The new set, S', has the form S' = S {x}. The ‑ ‑ power set of S' contains 2
power set of S' contains 2
n-1n-1subsets. subsets.
Adding the element x back into each of these Adding the element x back into each of these subsets creates a second collection of 2
subsets creates a second collection of 2
n-1n-1subsets. subsets.
The power set of S is the union of the power set The power set of S is the union of the power set for S' and the elements in the second collection.
for S' and the elements in the second collection.
Finding All Subsets (concluded) Finding All Subsets (concluded)
The "recursive" part of the algorithm The "recursive" part of the algorithm
involves creating the power set of S'. Just involves creating the power set of S'. Just
repeat the process by removing an repeat the process by removing an
element from S' to form (S')' which is a set element from S' to form (S')' which is a set
with n-2 elements. The stopping condition with n-2 elements. The stopping condition
occurs when removing an element leaves occurs when removing an element leaves
the empty set {}. The power set of empty the empty set {}. The power set of empty
set is the one-element set whose only
set is the one-element set whose only
Listing Permutations Listing Permutations
A A permutation permutation on n items (1, 2, . . ., n) is on n items (1, 2, . . ., n) is an ordered arrangement of the items. The an ordered arrangement of the items. The
number of permutations of n items is number of permutations of n items is
n! = n*(n-1)*(n-2)…(2)(1).
n! = n*(n-1)*(n-2)…(2)(1).
Listing Permutations Listing Permutations
(continued) (continued)
The recursive algorithm for n! traverses a The recursive algorithm for n! traverses a recursion tree. Permutations are leaf
recursion tree. Permutations are leaf nodes at the bottom level.
nodes at the bottom level.
Listing Permutations
Listing Permutations (continued) (continued)
Index 0: Index 0:
Use a loop to create n-1 copies of the array by Use a loop to create n-1 copies of the array by exchanging each element in the index range exchanging each element in the index range [1, n) with the element at index 0. The initial [1, n) with the element at index 0. The initial
array and the copies define all of the arrays array and the copies define all of the arrays
that have distinct values at index 0 and that have distinct values at index 0 and
correspond to the elements at level 1 in the correspond to the elements at level 1 in the
tree.
tree.
Listing Permutations
Listing Permutations (continued) (continued)
Index 1: Index 1:
For each of the n arrays with distinct elements For each of the n arrays with distinct elements at index 0, a recursive call is made with the
at index 0, a recursive call is made with the array and index 1 (next index). A loop takes array and index 1 (next index). A loop takes
the array argument and creates n-2 new the array argument and creates n-2 new
arrays by exchanging each element in the arrays by exchanging each element in the
range [2,n) with the element at index 1. For range [2,n) with the element at index 1. For
each array at level 1, the array and the n-2 each array at level 1, the array and the n-2
copies represent n-1 distinct ordering of copies represent n-1 distinct ordering of
elements at indices 0 to 1.
elements at indices 0 to 1.
Listing Permutations
Listing Permutations (continued) (continued)
Listing Permutations
Listing Permutations (continued) (continued)
A recursive call is made for the each array A recursive call is made for the each array and for all of the copies that are created and for all of the copies that are created
during the loop (iterative process). As a during the loop (iterative process). As a
result, permutations are created and then result, permutations are created and then
displayed by following the different paths displayed by following the different paths
in the tree from left to right. The array at in the tree from left to right. The array at
the end of each path is a permutation.
the end of each path is a permutation.
The following shows the order in which
The following shows the order in which
Listing Permutations
Listing Permutations (continued) (continued)
permutation() permutation()
public static void permutation(Object[] permList) {
permute(permList, 0);
}
permute() permute()
private static void permute(Object[] permList, int index)
{
int i, j, arrSize = permList.length;
Object temp;
if (index == arrSize-1)
// display the permutation
System.out.println(Arrays.toString(permList));
else {
Object[] newPermList = new Object[arrSize];
for (i = 0; i < arrSize; i++) newPermList[i] = permList[i];
// find all permutations over the // range (index, arrSize)
permute() (concluded) permute() (concluded)
// exchange permList[index] with permList[i]
// for i=index+1 to the end of the array and // find all permutations
for (i=index+1; i < arrSize; i++) {
temp = permList[i];
permList[i] = permList[index];
permList[index] = temp;
newPermList = new Object[arrSize];
for (j = 0; j < arrSize; j++) newPermList[j] = permList[j];
permute(newPermList, index+1);
} }
Traveling Salesman Problem Traveling Salesman Problem
The Traveling Salesman Problem (TSP) The Traveling Salesman Problem (TSP) describes an interesting and challenging describes an interesting and challenging
combinatorial problem which can be stated combinatorial problem which can be stated
very simply. A salesman is responsible for n very simply. A salesman is responsible for n
cities in a territory that has paths that connect cities in a territory that has paths that connect
any two cities. The problem is to identify a tour any two cities. The problem is to identify a tour
(a simple cycle) that has the salesman visit (a simple cycle) that has the salesman visit
each city just once and finish up where he each city just once and finish up where he
started. The order of visits should minimize the started. The order of visits should minimize the
total distance traveled.
total distance traveled.
Traveling Salesman Problem Traveling Salesman Problem
(continued)
(continued)
Traveling Salesman Problem Traveling Salesman Problem
(continued) (continued)
The traveling salesman problem has a The traveling salesman problem has a variety of applications. For instance, a variety of applications. For instance, a
school district must arrange bus routes to school district must arrange bus routes to
pick up students at a variety of stops and pick up students at a variety of stops and
deliver them to the school. A robot arm deliver them to the school. A robot arm
must be programmed to move efficiently must be programmed to move efficiently
over a circuit board to drill holes and over a circuit board to drill holes and
solder connections.
solder connections.
Traveling Salesman Problem Traveling Salesman Problem
(continued) (continued)
Possible Tours: (n-1) * (n-2) * . . . * 2 * 1 Possible Tours: (n-1) * (n-2) * . . . * 2 * 1
= (n-1)!
= (n-1)!
For large n, the number of possible tours For large n, the number of possible tours is so large that an exhaustive search of all is so large that an exhaustive search of all
possible paths is unrealistic. No one has possible paths is unrealistic. No one has
found an algorithm to solve the general found an algorithm to solve the general
problem with polynomial runtime problem with polynomial runtime
efficiency.
efficiency.
Traveling Salesman Problem Traveling Salesman Problem
(concluded) (concluded)
Traveling Salesman problem is NP-complete. Traveling Salesman problem is NP-complete.
There is likely no solution with polynomial There is likely no solution with polynomial
running time.
running time.
We can use permutations to solve the We can use permutations to solve the
traveling salesman problem for relatively traveling salesman problem for relatively
small n. Create an array with the starting city small n. Create an array with the starting city
in position 0 and the other cities occupying in position 0 and the other cities occupying
the other positions. Check each permutation the other positions. Check each permutation
and find a tour of minimum distance.
and find a tour of minimum distance.
Dynamic Programming Dynamic Programming
Fibonacci Sequence Fibonacci Sequence : 0, 1, 1, 2, 3, 5, 8, 13, : 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, …
21, 34, 55, …
Recursive definition Recursive definition : :
2 n
1 n
0 n
2), fib(n
1) fib(n
1,
0,
fib(n)
Recursive fib() Recursive fib()
// recursive computation of Fibonacci number n public static int fib(int n)
{
// stopping conditions if (n <= 1)
return n;
else
// recursive step
return fib(n-1) + fib(n-2);
}
Dynamic Programming Dynamic Programming
(continued) (continued)
Running time for the recursive method fib(n) is Running time for the recursive method fib(n) is exponential due to the redundant function calls.
exponential due to the redundant function calls.
Dynamic Programming Dynamic Programming
(continued) (continued)
Recursive solution for fib(n) fails to Recursive solution for fib(n) fails to
partition problem into non-overlapping partition problem into non-overlapping
subproblems.
subproblems.
Top-Down Dynamic Top-Down Dynamic
Programming Programming
Top-down dynamic programming gains Top-down dynamic programming gains efficiency by storing previously computed efficiency by storing previously computed
values during a recursive process.
values during a recursive process.
Use an array that stores the return values from Use an array that stores the return values from intermediate method calls. The recursive step intermediate method calls. The recursive step
first checks the array to see whether the result first checks the array to see whether the result
has already been computed. If so, it directly has already been computed. If so, it directly accesses the value. If not, the recursive step accesses the value. If not, the recursive step
executes, then adds the result to the array for
executes, then adds the result to the array for
Top-Down Dynamic Top-Down Dynamic
Programming (continued)
Programming (continued)
fibDyn() fibDyn()
// computation of the nth Fibonacci number using // top down dynamic programming to avoid redundant // recursive method calls
public static int fibDyn(int n, int[] fibList) {
int fibValue;
// check for a previously computed result and return if (fibList[n] >= 0)
return fibList[n];
// otherwise execute the recursive algorithm // to obtain the result
fibDyn() (concluded) fibDyn() (concluded)
// stopping conditions if (n <= 1)
fibValue = n;
else
// recursive step
fibValue = fibDyn(n-1, fibList) + fibDyn(n-2, fibList);
// store the result and return its value fibList[n] = fibValue;
return fibValue;
}
Running Time of fibDyn() Running Time of fibDyn()
The figure shows that n+1 method The figure shows that n+1 method calls reach the bottom of the tree calls reach the bottom of the tree
followed by n-2 on the way back up. The followed by n-2 on the way back up. The
number of method calls to compute number of method calls to compute
fibDyn(n) is n + 1+ (n-2) = 2n-1.
fibDyn(n) is n + 1+ (n-2) = 2n-1.
Combinations with Dynamic Combinations with Dynamic
Programming Programming
Top-down dynamic programming can be used Top-down dynamic programming can be used to improve the recursive algorithm for C(n,k).
to improve the recursive algorithm for C(n,k).
Store intermediate results in the matrix commMat, Store intermediate results in the matrix commMat, which has n+1 rows and k+1 columns, where
which has n+1 rows and k+1 columns, where
commMat[i][j] is the solution for C(i,j). Initially all commMat[i][j] is the solution for C(i,j). Initially all
of the values in the matrix are set to -1. Each of the values in the matrix are set to -1. Each
recursive call to commDyn(n, k) first checks recursive call to commDyn(n, k) first checks
whether the value commMat[n][k] is nonzero. If
whether the value commMat[n][k] is nonzero. If
so, it uses the matrix element as its return value
so, it uses the matrix element as its return value
commDyn() commDyn()
// computation of C(n,k) using top down dynamic // programming to avoid redundant recursive
// method calls
public static int commDyn(int n, int k, int[][] commMat) {
int returnValue;
// check if value is already computed if (commMat[n][k] >= 0)
return commMat[n][k];
commDyn() (concluded) commDyn() (concluded)
if (n == k || k == 0) returnValue = 1;
else if (k == 1) returnValue = n;
else
// carry out the recursive step
returnValue = commDyn(n-1,k,commMat) + commDyn(n-1,k-1,commMat);
// before returning, assign value to the matrix commMat[n][k] = returnValue;
return returnValue;
}
Bottom-Up Dynamic Bottom-Up Dynamic
Programming Programming
Bottom-up dynamic programming builds Bottom-up dynamic programming builds
the solution in order, starting at the lowest the solution in order, starting at the lowest
level and moving upward, using values level and moving upward, using values
from the previous level.
from the previous level.
Bottom-Up Dynamic Bottom-Up Dynamic
Programming (continued) Programming (continued)
The combinations formula C(n,k) = C(n-1, The combinations formula C(n,k) = C(n-1, k) + C(n-1, k-1) indicates that we can
k) + C(n-1, k-1) indicates that we can
compute intermediate values for entries in compute intermediate values for entries in
row i by using results from row i-1. The row i by using results from row i-1. The
following table displays the matrix for n = following table displays the matrix for n =
6, k = 6. When n = k, the table of entries 6, k = 6. When n = k, the table of entries
is often called
is often called Pascal's Triangle Pascal's Triangle . .
Bottom-Up Dynamic Bottom-Up Dynamic
Programming (continued)
Programming (continued)
Bottom-Up Dynamic Bottom-Up Dynamic
Programming (continued) Programming (continued)
Bottom-up dynamic programming very Bottom-up dynamic programming very
efficiently computes C(n,k) by building the efficiently computes C(n,k) by building the
Pascal triangle.
Pascal triangle.
commDynB() commDynB()
// computation of C(n,k) using bottom-up // dynamic programming
public static int commDynB(int n, int k) {
// create an n+1 by k+1 matrix
int[][] commMat = new int[n+1][k+1];
int i, j;
commDynB() (continued) commDynB() (continued)
// rows range from 0 through n for (i=0; i <= n; i++)
// only generate columns 0 through k for (j = 0; j <= Math.min(i,k); j++)
// commMat[i][j] = 1 when j == 0 or j == i if (j == 0 || i == j)
commMat[i][j] = 1;
else
commMat[i][j] = commMat[i-1][j-1] + commMat[i-1][j];
// return the entry commMat(n,k) return commMat[n][k];
}
commDynB() (concluded)
commDynB() (concluded)
Knapsack Problem Knapsack Problem
Given a knapsack with limited capacity, Given a knapsack with limited capacity,
measured in volume, is to hold a set of items measured in volume, is to hold a set of items
that have specified sizes and values. Find a that have specified sizes and values. Find a
subset of objects that will fit into the knapsack subset of objects that will fit into the knapsack and provide the maximum value. The problem and provide the maximum value. The problem
is a prototype for many important is a prototype for many important
applications; for instance, transport companies applications; for instance, transport companies
want to load a truck, freight car, or ship with want to load a truck, freight car, or ship with
cargo that returns a maximum profit.
cargo that returns a maximum profit.
Knapsack Problem (continued) Knapsack Problem (continued)
A brute force solution of the knapsack problem A brute force solution of the knapsack problem checks all subsets of items, which is an
checks all subsets of items, which is an exponential algorithm.
exponential algorithm.
A dynamic programming solution applies the A dynamic programming solution applies the principle of optimality
principle of optimality to each item in the to each item in the
collection. The principle states that, no matter collection. The principle states that, no matter
what the first decision, the remaining decisions what the first decision, the remaining decisions
must be optimal with respect to any state in the must be optimal with respect to any state in the
algorithm that results from the first decision.
algorithm that results from the first decision.
Knapsack Problem (continued) Knapsack Problem (continued)
Solve the knapsack problem by using Solve the knapsack problem by using
the principle of optimality in the generation of the principle of optimality in the generation of
the knapsack matrix.
the knapsack matrix.
The mathematical definition of maxValueMat[i][cap] is The mathematical definition of maxValueMat[i][cap] is
where a
where a
jj= 1 if item = 1 if item
jjis in the subset and a is in the subset and a
jj= 0 if = 0 if itemj is not in the subset. After we build the matrix, itemj is not in the subset. After we build the matrix,
matValueMat[n][capacity] is the solution to the matValueMat[n][capacity] is the solution to the
problem.
problem.
i
1
j i cap
1
j .size)
item j j (
a and
.value) item j
j (
a
max
Knapsack Problem (continued Knapsack Problem (continued
// keep the same max value by default
maxValueMat[i][cap] = maxValueMat[i-1][cap];
// test if itemList[i] fits into the knapsack if (cap-itemList[i].size >= 0)
{
// test if maximum value increases
testMax = maxValueMat[i-1][cap-itemList[i].size] + itemList[i].value;
// if yes, assign new max
Use the following algorithm to determine maxValueMat[i][cap]
Use the following algorithm to determine maxValueMat[i][cap]
Knapsack Problem (continued) Knapsack Problem (continued)
item item size size value value
1 1 2 2 1 1
2 2 3 3 4 4
3 3 4 4 3 3
4 4 5 5 6 6
5 5 6 6 8 8
Knapsack Problem (continued) Knapsack Problem (continued)
2 cap .value
item 1
2 cap 1 0
row of
Contents
Knapsack Problem (continued) Knapsack Problem (continued)
5 cap
4 cap 3
2 cap
2 cap
.value item 2
.value item 1
.value item 2
.value item 1
0 2 row Contents
Knapsack Problem (continued) Knapsack Problem (continued)
6 cap 5
4 cap 3
2 cap
2 cap
.value item 2
.value item 1
.value item 2
.value item 1
0
3 row of
Contents
The Item Class The Item Class
The class Item describes the items in the The class Item describes the items in the knapsack. Two integer variables define the knapsack. Two integer variables define the
size and value of an object. To simplify size and value of an object. To simplify
access, we declare the members public. A access, we declare the members public. A
constructor creates an instance of the constructor creates an instance of the
class using two arguments for the size and class using two arguments for the size and
value.
value.
Item Class Item Class
// specifies the size and value of an item public class Item
{
public int size, value;
public Item(int size, int value) {
this.size = size;
this.value = value;
} }
Knapsack Class Knapsack Class
public class Knapsack {
// capacity of the knapsack private int capacity;
// the list of items
private Item[] itemList;
// the number of items (itemList.length) private int numItems;
// the knapsack matrix
private int[][] maxValueMat;
// initialize variables and build the knapsack matrix public Knapsack(Item[] list, int cap)
{ . . . }
Knapsack Class Knapsack Class
(concluded) (concluded)
// builds maxValueMat for specified capacity private void buildMaxValueMat()
{ . . . }
// displays capacity, items in knapsack, max value, // and unused capacity
public void displayKnapsack() { . . . }
}
buildMaxValueMat() buildMaxValueMat()
// builds maxValueMat for specified capacity private void buildMaxValueMat()
{
int i, cap, testMax;
// compute entries in the matrix for (i = 1; i <= numItems; i++)
for (cap = 1; cap <= capacity; cap++) {
// initially assume the max value for capacity // cap is produced by using items from 1 to i-1 maxValueMat[i][cap] = maxValueMat[i-1][cap];
buildMaxValueMat() buildMaxValueMat()
(concluded) (concluded)
// test if itemList[i] fits into the knapsack if (cap-itemList[i].size >= 0)
{
// test if maximum value increases testMax =
maxValueMat[i-1][cap-itemList[i].size] + itemList[i].value;
// if yes, assign new max
if (testMax > maxValueMat[i-1][cap]) maxValueMat[i][cap] = testMax;
} }
displayKnapsack() displayKnapsack()
Identify items in the knapsack solution by Identify items in the knapsack solution by going backwards from the item in the
going backwards from the item in the knapsack matrix, row n, column cap.
knapsack matrix, row n, column cap.
displayKnapsack() (continued) displayKnapsack() (continued)
// displays capacity, items in knapsack, max value, // and unused capacity
public void displayKnapsack() {
int i = numItems, cap = capacity;
// create label with capacity and maximum value System.out.println("Capacity: " + capacity +
" Value: " + maxValueMat[numItems][capacity]);
// list items in the knapsack by reading // from maxValueMat
System.out.println("Contents: ");
displayKnapsack() displayKnapsack()
(concluded) (concluded)
while (i > 0) {
// if values in successive rows are not equal, // itemList[i] is part of the solution
if (maxValueMat[i][cap] != maxValueMat[i-1][cap]) {
System.out.println(" item" + i + '(' + itemList[i].size + ',' +
itemList[i].value + ')');
// look for maximum value remaining space cap -= itemList[i].size;
} i--;
}
System.out.println(" Unused capacity: " + cap);
}
Program 29.1 Program 29.1
import java.util.Scanner;
public class Program29_1 {
public static void main(String[] args) {
// array of Item objects for the knapsack
Item[] itemList = {new Item(2,1), new Item(3,4), new Item(4,3), new Item(5,6), new Item(6,8)};
// use for keyboard input
Scanner keyIn = new Scanner(System.in);
int capacity;
Program 29.1 (concluded) Program 29.1 (concluded)
System.out.print("Enter the capacity: ");
capacity = keyIn.nextInt();
// create a knapsack object
Knapsack ks = new Knapsack(itemList,capacity);
// display the solution ks.displayKnapsack();
System.out.println();
} }
Program 29.1 (Runs) Program 29.1 (Runs)
Run 1:
Enter the capacity: 12 Capacity: 12 Value: 14 Contents:
item5(6,8) item4(5,6)
Unused capacity: 1 Run 2:
Enter the capacity: 19 Capacity: 19 Value: 21 Contents:
item5(6,8) item4(5,6)
Evaluating the Knapsack Evaluating the Knapsack
Problem Solution Problem Solution
Running time for the knapsack problem is Running time for the knapsack problem is O(nC), where n is the number of items, O(nC), where n is the number of items,
and C the capacity.
and C the capacity.
The amount of computation depends critically The amount of computation depends critically on C. For instance, if C = n the algorithm is on C. For instance, if C = n the algorithm is
O(n O(n
22), but if C = 2 ), but if C = 2
nn, the algorithm has running , the algorithm has running time O(n2
time O(n2
nn). ).
Backtracking Backtracking
With recursive backtracking, we move With recursive backtracking, we move forward and possibly several steps
forward and possibly several steps backward until reaching a solution.
backward until reaching a solution.
The 8-Queens problem attempts to position The 8-Queens problem attempts to position eight queens on a chessboard in such a way eight queens on a chessboard in such a way
that no two queens can attack each other.
that no two queens can attack each other.
8-Queens has an elegant solution 8-Queens has an elegant solution implemented by using backtracking.
implemented by using backtracking.
The 8-Queens Problem The 8-Queens Problem
A queen can be attacked by a queen A queen can be attacked by a queen in the same row or column and by a in the same row or column and by a
queen on one of the two diagonals.
queen on one of the two diagonals.
The 8-Queens Problem The 8-Queens Problem
(continued) (continued)
We build a solution column by column, We build a solution column by column, starting with column 0. In each
starting with column 0. In each
succeeding column, col, we move from succeeding column, col, we move from
row 0 to row 1, then to row 2, and so row 0 to row 1, then to row 2, and so
forth, until we find a "safe" cell where the forth, until we find a "safe" cell where the
queen can be positioned without begin queen can be positioned without begin
vulnerable to attack by any of the other vulnerable to attack by any of the other
queens already positioned on the board.
queens already positioned on the board.
The 8-Queens Problem The 8-Queens Problem
(continued)
(continued)
The 8-Queens Problem The 8-Queens Problem
(continued) (continued)
No safe cell may exist in column col. No safe cell may exist in column col.
The approach fails in column 5, because The approach fails in column 5, because placing a queen in any of the eight rows placing a queen in any of the eight rows
leaves it vulnerable to attack by one of the leaves it vulnerable to attack by one of the
five queens on the board. Backtrack back to five queens on the board. Backtrack back to
column 4.
column 4.
Move forward to another row in column Move forward to another row in column
col if a queen at (row,col) does not lead to
col if a queen at (row,col) does not lead to
The 8-Queens Problem The 8-Queens Problem
(continued)
(continued)
The 8-Queens Problem The 8-Queens Problem
(continued) (continued)
We move forward to column 5 and We move forward to column 5 and
continue the algorithm. Placing the queen continue the algorithm. Placing the queen
in cell (7,4) is a short-lived success, in cell (7,4) is a short-lived success,
because it does not permit any queen to because it does not permit any queen to
be safely positioned in column 5.
be safely positioned in column 5.
Backtrack may involve going back more than Backtrack may involve going back more than one column to find a solution.
one column to find a solution.
The 8-Queens Problem The 8-Queens Problem
(continued)
(continued)
Implementing the 8-Queens Implementing the 8-Queens
Solution Solution
The method placeQueens() implements The method placeQueens() implements the backtracking strategy.
the backtracking strategy.
safeLocation() checks if a queen at safeLocation() checks if a queen at
(row,col) is safe from attack by queens in (row,col) is safe from attack by queens in
columns 0 through col-1.
columns 0 through col-1.
safeLocation() safeLocation()
// determine if cell (row,col) is safe from
// attack by queens in cells (queenList[0],0), ..., // (queenList[col-1],col-1)
public static boolean safeLocation(int row, int col, int[] queenList)
{
int qRow, qCol;
safeLocation() safeLocation()
(concluded) (concluded)
// check previous columns only
for (qCol = 0; qCol < col; qCol++) {
qRow = queenList[qCol];
if (qRow == row) // same row return false;
else if (qCol == col) // same col return false;
// can they attack on a diagonal?
else if(qCol-qRow == col-row ||
qCol+qRow == col+row) return false;
placeQueens() placeQueens()
The static method placeQueens() returns The static method placeQueens() returns a boolean value that indicates when a
a boolean value that indicates when a current partial solution will lead to a current partial solution will lead to a
complete solution of the problem. That is, complete solution of the problem. That is,
when it is possible to take the current when it is possible to take the current
arrangement of queens in columns 0 to arrangement of queens in columns 0 to
col-1 (defined by queenList) and locate col-1 (defined by queenList) and locate
safe cells for the queens in the remaining safe cells for the queens in the remaining
columns.
columns.
placeQueens() (continued) placeQueens() (continued)
// cells (queenList[0],0), ..., (queenList[col-1],col-1) // are safe positions; determine if the solution can
// be extended to columns col, col+1, ..., 7 public static boolean placeQueens(
int[] queenList, int col) {
int row;
boolean foundLocation;
if (col == 8) // stopping condition foundLocation = true;
else {
foundLocation = false; // start with row 0
placeQueens() placeQueens()
(continued) (continued)
while (row < 8 && !foundLocation) {
// check whether cell (row, col) is safe;
// if so, assign row to queenList and call // placeQueens() for next column; otherwise, // go to the next row
if (safeLocation(row,col,queenList) == true) {
// found good location queenList[col] = row;
// recursive step; try to place queens in // columns col+1 through 7
foundLocation = placeQueens(queenList,col+1);
if (!foundLocation)
// use next row since current one does
placeQueens() placeQueens()
(concluded) (concluded)
else
// current row fails; go to the next row row++;
} // end while }
// pass success or failure back to previous col return foundLocation;
}
queens() queens()
The method queens() facilitates calling the The method queens() facilitates calling the recursive method placeQueens().
recursive method placeQueens().
queens() (concluded) queens() (concluded)
// place a queen in (row, 0) and try to find a solution // to the 8-Queens problem for columns 1, 2, ..., 7
public static boolean queens(int[] queenList, int row) {
// place first queen at (row,0) queenList[0] = row;
// locate remaining queens in columns 1 through 7 if (placeQueens(queenList, 1))
return true;
else
return false;
}
Displaying a ChessBoard Displaying a ChessBoard
Class ChessBoard simulates a chess board for Class ChessBoard simulates a chess board for the 8-Queens problem.
the 8-Queens problem.
The ChessBoard class has a private instance variable The ChessBoard class has a private instance variable board
board which is an 8 by 8 two dimension array of which is an 8 by 8 two dimension array of ‑ ‑ boolean values.
boolean values.
The method setQueens() has the array argument The method setQueens() has the array argument queenList which identifies the location of queens on queenList which identifies the location of queens on
the board as (row,col) pairs and creates a the board as (row,col) pairs and creates a
representation of a chess board by assigning the representation of a chess board by assigning the
[row][col] entry a value true if a queen is present [row][col] entry a value true if a queen is present
and the value false to indicate a free cell.
and the value false to indicate a free cell.
Displaying a ChessBoard Displaying a ChessBoard
(concluded)
(concluded)
Program 29.2 Program 29.2
import java.util.Scanner;
public class Program29_2 {
public static void main (String[] args) {
int row;
// the array needed by the 8-Queens algorithm int[] queenList = new int[8];
// board will display the solution ChessBoard board = new ChessBoard();
Scanner keyIn = new Scanner(System.in);
// enter a starting row for queen in column 0 System.out.print("Enter row for queen " +
"in column 0: ");
row = keyIn.nextInt();
Program 29.2 (concluded) Program 29.2 (concluded)
// see if there is a solution
if (Queens.queens(queenList, row)) {
// insert the solution into the chessboard board.setQueens(queenList);
// display the solution board.drawBoard();
} else
System.out.println("No solution");
} }
Program 29.2 (Run #1) Program 29.2 (Run #1)
Enter row for queen in column 0: 2 0 1 2 3 4 5 6 7
0 - Q - - - - 1 - - - Q - - 2 Q - - - - 3 - - - Q - 4 - - - Q - - - - 5 - - - Q 6 - - Q - - - - - 7 - - - - Q - - -
Program 29.2 (Run #2) Program 29.2 (Run #2)
Enter row for queen in column 0: 5 0 1 2 3 4 5 6 7
0 - Q - - - - 1 - - - Q - - - - 2 - - - Q - - 3 - - - Q 4 - - Q - - - - - 5 Q - - - - 6 - - - Q - 7 - - - - Q - - -