cplib-cpp

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub hitonanode/cplib-cpp

:warning: Bounded knapsack problem (Pisinger's algorithm)
(other_algorithms/bounded_knapsack.hpp)

Code

/**
 * @file bounded_knapsack.hpp
 * @brief Bounded knapsack problem (Pisinger's algorithm)
 * @author hitonanode
 * @date 2023/01/01
 */

#pragma once
#include <algorithm>
#include <cassert>
#include <numeric>
#include <utility>
#include <vector>

/**
 * @fn bounded_knapsack_nonnegative(const std::vector<int> &, int)
 * Solve bounded knapsack problem: maximize weights(S) s.t. weights(S) <= capacity
 * Complexity: O(sum(weights) max(weights)) (Pisinger's linear time algorithm)
 * @param weights nonnegative integers describing weights.
 * @param capacity knapsack capacity limit.
 * @return std::pair<int, std::vector<bool>> {maximal value of weights(S), S that maximizes weights(S)}
 * @sa https://www.sciencedirect.com/science/article/abs/pii/S0196677499910349
 * @sa https://stackoverflow.com/a/9997386/20904249
 * @sa https://qiita.com/lowking/items/a9393f6afb9a4e662c38
 */
std::pair<int, std::vector<bool>>
bounded_knapsack_nonnegative(const std::vector<int> &weights, int capacity) {

    for (int w : weights) assert(w >= 0);
    assert(capacity >= 0);

    auto chmax = [](int &x, int y) { x = std::max(x, y); };

    int b = 0, w_bar = 0;
    const int n = weights.size();
    for (b = 0; b < n and w_bar + weights.at(b) <= capacity; ++b) w_bar += weights.at(b);

    if (b == n) return std::make_pair(w_bar, std::vector<bool>(n, true));

    int r = 0;
    for (int w : weights) r = std::max(r, w);

    const int O = r - 1; // DP table range: [capacity - r + 1, capacity + r]
    std::vector dp(n - b + 1, std::vector<int>(2 * r));
    for (int i = 0; i <= O; ++i) dp.front().at(i) = -1;
    dp.front().at(O + w_bar - capacity) = b;

    for (int t = b; t < n; ++t) {
        const std::vector<int> &dpprv = dp.at(t - b);
        std::vector<int> &dpnxt = dp.at(t - b + 1);
        dpnxt = dpprv;

        for (int i = 0; i <= O; ++i) chmax(dpnxt.at(i + weights.at(t)), dpprv.at(i));

        for (int i = O + weights.at(t); i >= O + 1; --i) {
            for (int j = dpnxt.at(i) - 1; j >= dpprv.at(i); --j) {
                chmax(dpnxt.at(i - weights.at(j)), j);
            }
        }
    }

    for (int z = O; z >= 0; --z) {
        if (dp.back().at(z) >= 0) {
            const int sol = capacity - O + z;
            std::vector<bool> ret(b, true);
            ret.resize(n, false);

            for (int t = n - 1; t >= b; --t) {
                const std::vector<int> &dpprv = dp.at(t - b), &dpnxt = dp.at(t - b + 1);
                while (dpnxt.at(z) < b) {
                    int znxt = z + weights.at(dpnxt.at(z));
                    if (znxt >= int(dpnxt.size()) or dpnxt.at(z) >= dpnxt.at(znxt)) break;
                    ret.at(dpnxt.at(z)) = false;
                    z = znxt;
                }
                if (z >= weights.at(t) and dpprv.at(z - weights.at(t)) >= dpnxt.at(z)) {
                    z -= weights.at(t);
                    ret.at(t) = true;
                }
            }

            return {sol, ret};
        }
    }
    exit(1); // Not occur
}

/**
 * @fn bounded_knapsack(const std::vector<int> &, int)
 * Solve bounded knapsack problem: maximize weights(S) s.t. weights(S) <= capacity
 * Complexity: O(sum(abs(weights)) max(abs(weights)))
 * @param weights Integers describing weights. Negative values are allowed.
 * @param capacity Knapsack capacity limit.
 * @return std::pair<int, std::vector<bool>> {maximal value of weights(S), S that maximizes weights(S)}
 */
std::pair<int, std::vector<bool>> bounded_knapsack(const std::vector<int> &weights, int capacity) {
    assert(capacity >= 0);
    std::vector<int> tmp = weights;
    for (int &w : tmp) {
        if (w < 0) w = -w, capacity += w;
    }
    auto sol = bounded_knapsack_nonnegative(tmp, capacity);
    for (int i = 0; i < int(weights.size()); ++i) {
        if (weights.at(i) < 0) {
            capacity += weights.at(i);
            sol.second.at(i).flip();
        }
    }
    return sol;
}
Traceback (most recent call last):
  File "/opt/hostedtoolcache/Python/3.13.5/x64/lib/python3.13/site-packages/onlinejudge_verify/documentation/build.py", line 71, in _render_source_code_stat
    bundled_code = language.bundle(stat.path, basedir=basedir, options={'include_paths': [basedir]}).decode()
                   ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.13.5/x64/lib/python3.13/site-packages/onlinejudge_verify/languages/cplusplus.py", line 187, in bundle
    bundler.update(path)
    ~~~~~~~~~~~~~~^^^^^^
  File "/opt/hostedtoolcache/Python/3.13.5/x64/lib/python3.13/site-packages/onlinejudge_verify/languages/cplusplus_bundle.py", line 312, in update
    raise BundleErrorAt(path, i + 1, "#pragma once found in a non-first line")
onlinejudge_verify.languages.cplusplus_bundle.BundleErrorAt: other_algorithms/bounded_knapsack.hpp: line 8: #pragma once found in a non-first line
Back to top page
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy