Memra

Modeling OilKnapsack as a DP

◈ 5 cards

Recast the AU final project as 0/1 knapsack with a storage penalty, and answer the six rubric tasks: subproblems, recurrence, acyclicity, base cases, reconstruction, running time.

The project, restated

The AU final project (OilKnapsack, 20% of your grade) is graded entirely on the dynamic-programming method, so this lesson walks the six tasks the rubric names, one by one.

> An oil company will produce barrels this month. There are orders; order wants barrels for a total price (not per barrel) — and may be negative. Each order is filled wholly or not at all, and at most once. The company need not sell all its oil, but pays storage of dollars per unsold barrel. Choose which orders to fill to maximize profit (which itself may be negative). Design an algorithm.

First, recognize the shape. Orders are items, the barrels are an item's weight, and the production is the knapsack capacity — you cannot sell more than you produce, so . This is 0/1 knapsack (whole-or-nothing items) with two twists the textbook version lacks: prices can be negative, and the objective subtracts a storage cost on whatever you do not sell.

Task 1 — Define the subproblems

The storage term depends on how many barrels stay unsold, which is . So we make the barrels sold an explicit dimension. Let or if selling exactly barrels from the first orders is impossible. There are such subproblems, indexed by and .

We deliberately track revenue at each sold-amount rather than folding storage in immediately, because the storage charge is a single end-of-month adjustment — we apply it once, at the very end, over all .

Task 2 — Relate the subproblems recursively

For order you make a binary choice: don't fill it (revenue and barrels unchanged) or fill it (gain revenue and barrels): The "fill" branch is legal only when (you can't sell barrels through this order if the order alone exceeds ) and when (the smaller amount must itself be reachable). Because may be negative, the will naturally skip an unprofitable order whenever skipping yields more revenue — no special case needed.

The final answer applies storage after the table is full: This is where "need not sell all the oil" lives: we let range over every feasible sold-amount and pick the best after charging storage on the leftover barrels.

Task 3 — Argue the relation is acyclic

Every value depends only on row (entries and ). Draw the subproblem graph with an edge from each cell to the cells it reads: all edges point from row strictly back to row . A graph whose every edge decreases the row index can contain no cycle — the rows give a topological order. So the recurrence is acyclic and a bottom-up fill in order of increasing always finds its dependencies already computed. (This is the acyclicity argument the rubric asks for, stated explicitly.)

Task 4 — Provide base cases

The empty selection sells barrels for $\$0$: With no orders you cannot sell any barrels, so every sold-amount except is unreachable. The sentinel is what makes the "need not fill the bag" semantics correct: unreachable sold-amounts never win the final .

Task 5 — Construct an optimal solution

The value table tells you how much profit; to report which orders to fill you trace back. Let b* be the sold-amount that won the final . Walk from down to : if then order was filled (its row changed the value) — record it and set . Otherwise it was skipped. This is the same stored-choice traceback as rod cutting and LCS, and it costs .

Task 6 — Analyze the running time

Filling the table is two nested loops: from to , and from to , with work per cell. That is cells. The final storage scan over is and the traceback is . Total: , matching the bound the project demands. As with textbook knapsack this is pseudo-polynomial is a number, written in bits, so is exponential in the input's bit-length.

A tiny worked instance

barrels, storage $s = \$3$ per unsold barrel. Orders $(q, p)(3, \$20), (2, \$15), (4, \$25)$.

Enumerate feasible sold-amounts and their best revenue, then charge storage:

soldbest revenueprofit
(order 2)
(order 1)
(order 3)
(orders 1+2)

The optimum is profit $\$35\{1, 2\}$ and selling all 5 barrels — storage is zero because nothing is left over. Lesson 11.2 computes exactly this with the bottom-up table.

In the problemIn the DPConcretelyorder ian itemfilled whole or notbarrels q_iitem weightconsumes capacityproduction Pcapacitysum q_i <= Pprice p_iitem valuemay be negativestorage send adjustment- s(P - b), onceb = barrels sold; the other P - b stay in the tank.
Recognising the shape. The two accented rows are the only departures from textbook 0/1 knapsack — a value that may be negative, and a cost charged on what you *do not* take.
CaseWhenbest[i][b]basei = 0, b = 00basei = 0, b >= 1−∞ (unreachable)skip order ialways legalbest[i-1][b]fill order iq_i <= b, reachablebest[i-1][b-q_i] + p_ianswertable fullmax_b ( best[n][b] - s(P-b))Storage is applied once, after the table is full.
The whole recurrence on one card: base, skip, fill (legal only when the order fits and the smaller amount is reachable), then the final max over every b after charging storage once.
NORMAL ~/memra/learn/comp-372/modeling-oilknapsack-as-dp utf-8 LF