【问题标题】:0/1 Knapsack witness generation0/1 背包见证生成
【发布时间】:2014-12-20 22:03:28
【问题描述】:

我写了一个背包类,我用它来解决背包算法。该课程有效,并且正在使用动态规划算法来解决问题。

我在代码中实现了一些优化,以便我使用线性 O(W) 空间来找到最大值,但是当我尝试找到见证时,我仍然需要 O(nW) 空间来保存布尔值表。

谁能告诉我是否有可能找到最大容量的背包的见证人,空间更小,复杂度为 O(nW),这里 W 是背包容量。

如果您认为代码中可能还有更多优化,也请告诉他们。

class Knapsack{
private:
  vector< int > value, weight, answer, DP;
  vector< bool > isin;
  int capacity;

public:
  Knapsack( vector< int > value, vector< int > weight, int capacity, bool needWitness ){
    this->value = value;
    this->weight = weight;
    this->capacity = capacity;

    this->answer.clear(); this->isin.clear(); this->DP.clear();
    this->DP.resize( capacity + 1, false );

    if ( needWitness ){
      this->isin.resize( value.size() * (capacity + 1), false );
      solveWithWitness();
    }
    else{
      solveWithoutWitness();
    }

  }

  void solveWithoutWitness(){
    for ( int i = 0; i < value.size(); i++ ){
      for ( int w = capacity; w >= weight[i]; w-- ){
        if ( DP[w] < value[i] + DP[w - weight[i]] ){
          DP[w] = value[i] + DP[w - weight[i]];
        }
      }
    }
  }

  void solveWithWitness(){
    for ( int i = 0; i < value.size(); i++ ){
      for ( int w = capacity; w >= weight[i]; w-- ){
        if ( DP[w] < value[i] + DP[w - weight[i]] ){
          DP[w] = value[i] + DP[w - weight[i]];
          isin[ i*capacity + w ] = true;
        }
      }
    }
    int position = value.size()-1;
    int w = capacity;
    while ( position >= 0 ){
      if ( isin[ position*capacity + w ] ){
        answer.push_back( position );
        w -= weight[position];
      }
      position--;
    }
  }


  vector< int > getWitness(){
    return this->answer;
  }

  int solution(){
    return DP[capacity];
  }

};

【问题讨论】:

    标签: algorithm dynamic-programming knapsack-problem


    【解决方案1】:

    你到处都在使用 O,所以我可以给你一个有点复杂和尴尬的理论解决方案,但仍然满足你想要的时间限制:

    在没有见证人的情况下运行 DP n/2 步;它告诉您仅使用前 n/2 个项目可以达到 W 权重中的哪一个。现在对剩余的 n/2 个步骤运行 DP,以跟踪前 n/2 个项目需要多少重量才能到达每个单元格。

    如果你天真地以递归方式应用这个过程,你会得到一个看起来像 T(n, W)

    但我们计算出前 n/2 件物品需要多少重量。称之为w。我们只需要关心 DP 数组的前 w 个条目。所以前半部分递归应该花费 T(n/2, w) 时间,后半部分递归应该花费 T(n/2, Ww) 时间,而到达那里所需的工作需要 O(nW) 时间。

    T(n, W)

    【讨论】:

    • 感谢您的回复。您说过“现在为剩余的 n/2 个步骤运行 DP,以跟踪前 n/2 个项目需要多少重量才能到达每个单元格”。你能更详细地解释一下这一步吗?
    • 它类似于 with-witness DP,不同之处在于您只跟踪 n/2-items 之后的单元格,而不是整个反向指针链。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-28
    • 2013-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多