简体   繁体   中英

Implementing Pseudopolynomial DP Subset Sum

I tried implementing the algorithm proposed on the Wikipedia page for the pseudo-polynomial time algorithm for subset sum where we aim to determine if there exists a nonempty subset of {x_1, ..., x_N} which sums to zero. So we set a range going from the sum of the negative numbers (A) up to the sum of positive numbers (B), and create a matrix to hold values Q(i, s) for 1 ≤ i ≤ N and A ≤ s ≤ B. Then for filling it up, we should initially set Q(1, s):= (x_1 == s), and for the recursive case we set Q(i, s):= Q(i − 1, s) or (xi == s) or Q(i − 1, s − xi), for A ≤ s ≤ B.

Here's my shot at this, where inp contains the input set. I keep track of the "real" index of s in the variable arrindex, because s may be some negative number and I can't index vectors at a negative.

vector<vector<bool>> result (inp.size(), vector<bool>(abs(B-A)+1)); // initialize results matrix
for(int s = A,arrindex=0; s <= B; s++,arrindex++){
    if(s == inp[0])
        result[0][arrindex] = true;
for(int i = 1; i < inp.size(); i++){
    for(int s = A,arrindex=0; s <= B; s++,arrindex++){
        // CHECK: Q(i, s) := Q(i − 1, s) or (xi == s) or Q(i − 1, s − xi),  for A ≤ s ≤ B
        if(s == inp[i] || result[i-1][arrindex] || result[i-1][abs((s - inp[i])-A)])
            result[i][arrindex] = true;
    }
}

My attempt gives an answer, but it seems to often not be correct. As a simple example, if my input is {-2, 1}, the answer should be no, but the matrix I obtain is

1 0 0 0
1 1 0 1

Which I think would indicate a "yes", right? So my question is, did I implement this incorrectly? Or am I interpreting incorrectly?

I think the term result[i - 1][abs((s - inp[i]) - A)] is not correct. It should be:

A <= s - inp[i] && s - inp[i] <= B && result[i - 1][s - inp[i] - A]

You can avoid nested vector s using a simple lambda function to mimic a matrix:

const auto n_rows = inp.size();
const auto n_cols = static_cast<std::size_t>(B - A + 1);
auto q = [qm = std::vector<bool>(n_rows * n_cols), n_rows, A]
         (auto i, auto j) mutable
         { return qm[i + (j - A) * n_rows]; };

for (auto j = A; j <= B; ++j)
    q(0, j) = (inp[0] == j);

for (std::size_t i = 1; i < n_rows; ++i)
    for (auto j = A; j <= B; ++j)
        q(i, j) = (inp[i] == j || q(i - 1, j) || 
                  (A <= j - inp[i] && j - inp[i] <= B && q(i - 1, j - inp[i])));

const bool has_zero_subset = q(n_rows - 1, 0);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM