10.19

From The Algorithm Design Manual Solution Wiki
Jump to navigation Jump to search

Idea: The task is the classic Partition problem. Let S = ∑wi. If S is odd we can stop – two equal halves are impossible. Otherwise we look for a subset of the suit-cases whose weight is exactly S/2. A simple bit-set dynamic programme finds this in O(m · S) time (or O(m · S/64) with machine words) and O(S) memory.

def divide_equal(w): S = sum(w) if S & 1: # odd total return None # impossible target = S // 2 dp = [False]*(target+1) prev = [-1]*(target+1) # reconstruction array dp[0] = True for idx,weight in enumerate(w): for s in range(target, weight-1, -1): if not dp[s] and dp[s-weight]: dp[s] = True prev[s] = idx # record suitcase used to reach s if not dp[target]: return None # no subset of weight S/2 # rebuild one driver's load load1, s = [], target while s: i = prev[s] load1.append(i) # suitcase i goes to driver 1 s -= w[i] load2 = [i for i in range(len(w)) if i not in load1] return load1, load2
Explanation 1. Scan the list once, updating the 1-dimensional table dp: dp[s] is True ⇔ some subset seen so far weighs s. 2. We iterate s backwards so every suitcase is used at most once. 3. When finished, dp[S/2] tells us whether equal sharing is possible. 4. Array prev remembers which suitcase first achieved each sum, so we can trace back and list the items for the first driver; the rest automatically belong to the second. Complexities • Time = Θ(m·S) (bit-parallel ≈ m·S/word_size) • Space = Θ(S) For typical airline limits (m ≤ 50, weights ≤ 30 kg) this runs in well under a millisecond.


Back to Chapter 10