--------------------------------------------------------------------------- COMP 731 - Data Struc & Algorithms - Lecture 24 - Thursday, August 31, 2000 --------------------------------------------------------------------------- Today: Dynamic Programming, continued o Subset Sum SUBSET SUM Given: Numbers a_1, ..., a_N ; B Find: T s.t. Sum a_i = B, if such a T exists, or i in T answer "No" if no such T exists. idea 1: As before: First look at Yes/No version; then extract answer for Yeses. idea 2: Main part: generalize the right way! / True if there exists a subset a_1... a_n that sum to b Let A[n,b] = | \ False otherwise idea 3: right recursively, exploiting optimal substructure / F if b<0 or n<0 A[n,b] = | T if b=0 and n>=0 \ A[n-1,b] || A[n-1,b-a_n] otherwise 1 2 3 4 5 ......... Example: 3 2 3 6 2 ; 7 0 1 2 3 4 5 6 7 <-- b --------------------------------- 0 | T | F : F : F : F : F : F : F | A[n-1,b-a_n] A[n-1, b] ----============================= \ /|\ 1 | T | F : F : T : F : F : F : F | \ | --------------------------------- \ | 2 | T | F : T : T : F : T : F : F | A[n,b] --------------------------------- 3 | T | F : T : T : F : T : T : F | Show how to mark the true --------------------------------- entries with an up-arrow or 4 | T | F : T : T : F : T : T : F | a diagonal arrow. --------------------------------- 5 | T | F : T : T : T : T : T : T | <== goal Total time: O(NB) --------------------------------- /|\ n * Now ask if can do in O(B) space, saving just the last TWO rows. --------------------------------- | T | F : T : T : F : T : T : F | --------------------------------- | T | F : T : T : T : T : T : T | --------------------------------- Keep "shifting" the window. Either move row 2 to row 1 -- or keep track of which row is the "logical" bottom row. * Now as if can do in O(B) space, saving just ONE row. --------------------------------- | T | F : T : T : F : T : T : F | --------------------------------- Keep "overwriting" the row * Now, finally, how can we use one row and recover our solution?? F -> 0 T -> a positive number. The number indicates which item a_n you took to make this value A[b] 1 2 3 4 5 ......... Example: 3 2 3 6 2 ; 7 0 1 2 3 4 5 6 7 <-- b --------------------------------- |-1 | 0 : 0 : 0 : 0 : 0 : 0 : 0 | --------------------------------- item 1 has value 3: 0 1 2 3 4 5 6 7 <-- b --------------------------------- |-1 | 0 : 0 : 1 : 0 : 0 : 1 : 0 | --------------------------------- item 2 has value 2: 0 1 2 3 4 5 6 7 <-- b --------------------------------- |-1 | 0 : 2 : 1 : 0 : 2 : 1 : 0 | --------------------------------- item 3 has value 3: 0 1 2 3 4 5 6 7 <-- b --------------------------------- |-1 | 0 : 2 : 1 : 0 : 2 : 1 : 0 | --------------------------------- item 4 has value 6: 0 1 2 3 4 5 6 7 <-- b --------------------------------- |-1 | 0 : 2 : 1 : 0 : 2 : 1 : 0 | --------------------------------- item 5 has value 2: 0 1 2 3 4 5 6 7 <-- b --------------------------------- |-1 | 0 : 2 : 1 : 5 : 2 : 1 : 5 | --------------------------------- To recover solution, start at b=7. It is non-zero -- it says 5. So take item 5. Item 5 has cost 2, so you have 7-2=5 units less 0 1 2 3 4 5 6 7 <-- b --------------------------------- |-1 | 0 : 2 : 1 : 5 : 2 : 1 : 5 | --------------------------------- * Take 5 *<------- Take 2 *<------- Take 1 *<----------- DONE No significance to the -1; will just have to treat A[0] specially. Finally, A[0] = -1 For i = 1 to B do A[i]=0; for n = 1 to N do for b = B downto 1 // you have to go backwards?! Why? // update A[b] if (A[b]==0) and (b-a[n]>=0) and A[b-a[n]]) then A[b] = n To recover solution: if A[B]==0 then print "No solution is possible" else b = B while b>0 print "Take item" A[b] b = b - a[A[b]]