【问题标题】:Knapsack Problem: Why do I need a 2 dimensional DP Matrix背包问题:为什么需要二维 DP 矩阵
【发布时间】:2021-04-22 22:49:41
【问题描述】:

我遇到了一些经典的背包解决方案,它们总是构建一个二维 DP 数组。 在我看来,我下面的代码解决了经典的背包问题,但只有一个 1-dim DP 数组。 谁能告诉我我的解决方案在哪里不起作用,或者为什么它与 2D-DP 版本相比计算效率低?

可以在此处找到 2D-DP 版本 https://www.geeksforgeeks.org/python-program-for-dynamic-programming-set-10-0-1-knapsack-problem/

示例输入:

weights = [(3,30),(2,20),(1,50),(4,30)]
constraint = 5

我的解决方案:

def knapsack(weights,constraint):
    n = len(weights)

    #define dp array
    dp = [0]*(constraint+1) 

    #start filling in the array
    for k in weights:
        for i in range(constraint,k[0]-1,-1):
            dp[i] = max(dp[i],dp[i-k[0]]+k[1])
    return dp[constraint]

【问题讨论】:

  • 好吧,您的weights 输入是一个二维数组。您是否有指向您不喜欢的对比解决方案的链接?
  • 您是否有代码无法运行的测试用例?
  • 嗨蒂姆 - 感谢您的回答,这是有道理的,但在这样的二维数组中转换输入数据会不会计算效率低下? [链接] (geeksforgeeks.org/…)
  • @TimRoberts OP 正在讨论数组 dp。通常它是用一个二维数组来实现的,其中每一行都是从前一行填充的,答案在最后一行的末尾。 OP 正在覆盖同一行以节省内存。
  • @SufianLatif 感谢您的澄清,我在原始问题中添加了更多文本。我只是想知道为什么大多数提议的解决方案都使用 2D-DP,如果使用 1D-DP 也同样有效并且可以节省内存。

标签: python dynamic-programming knapsack-problem


【解决方案1】:

使用 O(nW) 内存的版本更直观,可以轻松检索产生最佳答案值的项目子集。

但是,使用 O(n + W) 的内存,我们不能直接检索这个子集。虽然可以做到这一点,但可以使用 https://codeforces.com/blog/entry/47247?#comment-316200 中解释的分而治之的技术。

Sample code

#include <bits/stdc++.h>
 
using namespace std;
using vi = vector<int>;
#define FOR(i, b) for(int i = 0; i < (b); i++)
 
template<class T>
struct Knapsack{
  int n, W;
  vector<T> dp, vl;
  vi ans, opt, wg;
 
  Knapsack(int n_, int W): n(0), W(W),
    dp(W + 1), vl(n_), opt(W + 1), wg(n_){}
  
  void Add(T v, int w){
    vl[n] = v;
    wg[n++] = w;
  }
 
  T conquer(int l, int r, int W){
    if(l == r){
      if(W >= wg[l])
        return ans.push_back(l), vl[l];
      return 0;
    }
 
    FOR(i, W + 1)
      opt[i] = dp[i] = 0;
    int m = (l + r) >> 1;
    
    for(int i = l; i <= r; i++)
      for(int sz = W; sz >= wg[i]; sz--){
        T dpCur = dp[sz - wg[i]] + vl[i];
        if(dpCur > dp[sz]){
          dp[sz] = dpCur;
          opt[sz] = i <= m ? sz : opt[sz - wg[i]];
        }
      }
    
    T ret = dp[W];
    int K = opt[W];
    T ret2 = conquer(l, m, K) + conquer(m + 1, r, W - K);
    assert(ret2 == ret);
    return ret;
  }
 
  T Solve(){
    return conquer(0, n - 1, W);
  }
};
 
 
int main(){
  cin.tie(0)->sync_with_stdio(0);
 
  int n, W, vl, wg;
  cin >> n >> W;
  Knapsack<int> ks(n, W);
 
  FOR(i, n){
    cin >> vl >> wg;
    ks.Add(vl, wg);
  }
  
  cout << ks.Solve() << endl;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-19
    • 1970-01-01
    • 2013-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多