diff --git a/dynamic-programming/notes.md b/dynamic-programming/notes.md
index 857c51c3274b3e86dd398e15d5c649404fe93ad3..dd6cfdbaab3bc541e13a950a315d1c5d4503691e 100644
--- a/dynamic-programming/notes.md
+++ b/dynamic-programming/notes.md
@@ -36,8 +36,8 @@ so that every line is at most seven characters long, including spaces. The pena
Example: The wrapping
> x x x x
-> xxxx
-> xxxx
+> xxxx
+> xxxx
has a total penalty of `(7 - 7)² + (7 - 4)² + (7 - 4)² = 0 + 9 + 9 = 18`. But there is a wrapping with a lower total penalty.
@@ -50,35 +50,35 @@ Problem: Subject to an integer weight limit, what choice of items (allowing repe
## DAG
* Edges (actions):
- * … or
- * …
+ * Take one of the items or
+ * Take one kg of nothing.
* Vertices (situations):
- * …
+ * How much weight have we put into the backpack?
* Edge weights:
- * …
+ * The value of the item being taken
* Topological order:
- * …
+ * 0 → 1 → … `weightLimit`
* Goal:
- * …
+ * Compute a longest path from 0 to `weightLimit`
## Backpointer Class
* Information for the final result:
- * …
+ * What item did we take?
* Information to go back:
- * …
+ * What was the weight of the item just taken? (redundant with the item taken)
* Information to compare quality:
- * …
+ * What is the *total* value of all of the items taken so far?
## Choosing a Backpointer
* Exhaustive search:
- * Generate ….
- * Check that ….
+ * Generate items from the list or else 1 kg of nothing, but make sure that we don't try to go back to a negative total weight.
+ * Check that the item maximizes total value (the previous total value plus the value of the item used to go back).
## Example
-* Item Z ….
+* Item Z weighs 1 kg and is worth $0.
* Item A weighs 3 kg and is worth $10.
* Item B weighs 4 kg and is worth $14.
@@ -87,20 +87,20 @@ Problem: Subject to an integer weight limit, what choice of items (allowing repe
Weight (kg) Item Total Value (Back to Weight)
----------- ------ ----------- ----------------
0 [none] $0 ⊥
- 1 Item … … …
- 2 Item … … …
- 3 Item … … …
- 4 Item … … …
- 5 Item … … …
- 6 Item … … …
- 7 Item … … …
- 8 Item … … …
- 9 Item … … …
- 10 Item … … …
+ 1 Item Z 0 0
+ 2 Item Z 0 1
+ 3 Item A 10 0
+ 4 Item B 14 0
+ 5 Item Z 14 4
+ 6 Item A 20 3
+ 7 Item A 24 4
+ 8 Item B 28 4
+ 9 Item A 30 6
+ 10 Item A 34 7
Reversed Path
----
- 10 ← (Item …) ← …
+ 10 ← (Item A) ← 7 ← (Item A) ← 4 ← (Item B) ← 0
--------------------------------------------------------------------------------
diff --git a/dynamic-programming/src/features/knapsack/solver.js b/dynamic-programming/src/features/knapsack/solver.js
index 495b9e198445fb4ff055bf7ccd9c339b1b63a83f..ff780b5e39ca74a1f413a71705830c265adfd043 100644
--- a/dynamic-programming/src/features/knapsack/solver.js
+++ b/dynamic-programming/src/features/knapsack/solver.js
@@ -1,8 +1,9 @@
import { Item } from './items.js';
class Backpointer {
- constructor() {
- // TODO: stub
+ constructor(item, totalValue) {
+ this.item = item;
+ this.totalValue = totalValue;
}
}
@@ -13,5 +14,13 @@ function chooseBackpointer(items, backpointers) {
export function chooseItems(items, weightLimit) {
console.assert(Number.isInteger(weightLimit), `Tried to choose items with a noninteger weight limit ${weightLimit}.`);
- return []; // TODO: stub
+ const backpointers = [new Backpointer(undefined, 0)];
+ while (backpointers.length <= weightLimit) {
+ backpointers.push(chooseBackpointer(items, backpointers));
+ }
+ const reversedPath = [];
+ for (let weight = weightLimit; weight > 0; weight -= backpointers[weight].item.weight) {
+ reversedPath.push(…);
+ }
+ return reversedPath.reverse();
}