没有重复的背包

Knapsack without repetition

#include <iostream>
#include <vector>
#include <algorithm>
using std::vector;

int o_w(int W, const vector<int> &w) {
  vector<int> c(W+1);
  for (size_t i = 0; i < w.size(); ++i) {
      for(int j = W; j - w[i] >= 0; --j) {
            c[j] = std::max(c[j], c[j - w[i]] + w[i]);
      }
  }
  return c[W];
}

int opti_w(int W,const std::vector<int> &w,int n){
    std::vector<std::vector<int>> value(n+1,vector<int>(W+1,0));
    for(int i=0;i<=n;i++){
        for(int j=0;j<=W;j++){
            std::cout<<value[i][j]<<" ";
        }
        std::cout<<"\n";
    }

    for(int i=1;i<=n;i++){
      for(int j=1;j<=W;j++){
       //value[j][i]=std::max(value[j][i-1],value[j-w[i]][i-1]+w[i]);
      std::cout<<"i:"<<i<<" j:"<<j<<"\n";
      std::cout<<"value[i][j]:"<<value[i][j]<<"\n";
      std::cout<<"value[i-1][j]:"<<value[i-1][j]<<"\n";
      std::cout<<"w[i-1]:"<<w[i-1]<<"\n";
      std::cout<<"value[i-1][j-w[i-1]]:"<<value[i-1][j-w[i-1]]<<"\n";
      std::cout<<"value[i-1][j-w[i-1]]+w[i-1]:"<<value[i-1][j-w[i-1]]+w[i-1]<<"\n";
      value[i][j]=std::max(value[i-1][j],  value[i-1][j-w[i-1]] +w[i-1]  );
      }
    }
    
     for(int i=0;i<=n;i++){
        for(int j=0;j<=W;j++){
            std::cout<<value[i][j]<<" ";
        }
        std::cout<<"\n";
    }

    return value[n][W];
   // return value[W][n];
}

int main() {
  int n, W;
  std::cin >> W >> n;
  vector<int> w(n);
  for (int i = 0; i < n; i++) {
    std::cin >> w[i];
  }
  std::cout<<opti_w(W, w, n);
  //std::cout << o_w(W, w) << '\n';
}

在函数 opti_w 中,我以某种方式使用了错误的公式或出现错误,导致我无法获得正确的值,因为有时 j-[w-1] 变为负数,因此访问了不需要的元素。

函数o_w正确,可用于验证答案。

我该如何解决这个问题,解决方案中有什么不正确的地方。

你快到了。为什么不将 std::max 语句置于 if 条件下以处理 j-w[i-1] 毫无意义的情况?

for(int i=1;i<=n;i++){
   for(int j=1;j<=W;j++){
      value[i][j] = value[i-1][j];
      if(w[i-1]<=j){
       value[i][j]=std::max(value[i][j],  value[i-1][j-w[i-1]] +w[i-1]  );
       }
      }
    }

我只是更改了 if(w[i-1]<=j) 中的代码,它起作用了。