最大填充袋的算法(这不是背包0/1)

时间:2016-11-21 13:15:31

标签: algorithm dynamic-programming pseudocode

我正在处理一些需要我解决以下算法问题的任务:

<小时/> - 你收集了物品(它们的重量):[w1,w2,...,wn]
- 你有一个重量为:W的袋子 - 需要最大限度地填充袋子(尽可能多地填充)给定物品的子集。

所以这个不是“背包0/1”问题,因为我们只处理权重(我们只有一个参数用于项目)。因此,我假设它可能有一个解决方案(Knapsack是NP-complete)或某种算法可以得到近似正确的结果。

请不要向我推荐“贪心算法”,因为我认为应该有一种能够提供更好结果的算法。我认为它应该是一个使用“动态编程”的算法。

提前谢谢你:)

3 个答案:

答案 0 :(得分:2)

在这个特定情况下,您可以通过最小化行李中的可用空间来获得最大收益,因此将权重视为值。这个问题通常被称为subset sum problem,是背包问题家族的一个特例。

DP关系如下所示

enter image description here

在每个步骤中,您尝试在之前的元素集中添加最大值(不超过行李容量)加上新元素

子集求和问题的C ++实现回答了问题“我可以完全根据这些元素填充包吗?”和驱动程序如下

Calendar selected_cal = Calendar.getInstance();
selected_cal.setTime(selected_date);

//For next day                
Calendar nextDay = Calendar.getInstance();
nextDay.add(Calendar.DATE, 1);//Adding one day
nextDay.set(Calendar.HOUR_OF_DAY, 0);//Setting calendar for start hour of the day
nextDay.set(Calendar.MINUTE, 0);//Setting calendar for start minute of the day
nextDay.set(Calendar.SECOND, 0);//Setting calendar for start second of the day

//For previous days
Calendar previousDay = Calendar.getInstance();
previousDay.add(Calendar.DATE, -2);//Adding one day
previousDay.set(Calendar.HOUR_OF_DAY, 23);//Setting calendar for start hour of the day
previousDay.set(Calendar.MINUTE, 59);//Setting calendar for start minute of the day
previousDay.set(Calendar.SECOND, 59);//Setting calendar for start second of the day

if(selected_cal.getTimeInMillis()>=nextDay.getTimeInMillis()
|| selected_cal.getTimeInMillis()<previousDay.getTimeInMillis()){
        //Show error
}else{
        //Do what you want to do
}

复杂性为bool ssp(const vector<int>& v, const int& N) { vector<vector<int>> m( v.size() + 1 /* 1-based */, vector<int>(N + 1 /* 1-based */, 0) ); // The line above also took care of the initialization for base // cases f(i,0) = 0 and f(0,b) = 0 for (int i = 1; i <= v.size(); ++i) { // For each subset of elements for (int b = 1; b <= N; ++b) { // For each subcapacity int opt1 = m[i - 1][b]; int opt2 = -1; if (b - v[i - 1] >= 0) { // No caching to keep this readable opt2 = m[i - 1][b - v[i - 1]] + v[i - 1]; if (opt2 > b) opt2 = -1; // Not allowed } m[i][b] = max(opt1, opt2); } } return (m[v.size()][N] == N); } int main() { const vector<int> v = { 1, 3, 7, 4 }; const int N = 11; cout << "Subset sum problem can be solved with the given input: " << boolalpha << ssp(v, N); // true return 0; } ,其中O(N⋅I)是起始集中的元素数。这是假多项式的复杂性。

来源:Knapsack problem

答案 1 :(得分:1)

所描述的问题实际上不是0-1-Knapsack problem,而是一个特殊情况,也称为最大子集和问题,它被描述为here。它是NP - 完整,这意味着它不比0-1-Knapsack复杂化更容易。

话虽如此,它可以通过任何针对0-1-Knapsack问题的优化算法来解决,方法是将项目利润设置为等于其权重。总之,可以使用以下动态编程算法将其解决为最优性; s[i]表示i项和m是整数值状态空间的大小,其中m[i,s]表示使用项rage中的项可达到的最大值{ {1}}。

{0,...i}

正如原始问题中提到的那样,以下贪婪算法产生了2近似,这是针对背包问题的类似算法的修改。

for j from 0 to W do:
    m[0, j] := 0

for i from 1 to n do:
    for j from 0 to W do:
        if s[i] > j then:
            m[i, j] := m[i-1, j]
        else:
            m[i, j] := max(m[i-1, j], m[i-1, j-s[i]] + s[i])

答案 2 :(得分:0)

看起来像Spoj problem。而我的解决方案是:

#include <bits/stdc++.h>

using namespace std;

int TimTongLonNhatCoGioiHan(int*arr, int songuoichoi, int gioihan){

  int hmm = (int)(songuoichoi*songuoichoi/2);
  int map[hmm];

  int dem = 0, i, j, ox = songuoichoi - 1, oy = 0, result = 0, sum;
  for(i = ox; i > oy; --i){
    for(j = oy; j < ox; ++j){
      map[dem] = arr[i] + arr[j];

      // tinh tong lon nhat cua 3 so
      for(int k = 0; k < songuoichoi; ++k){
        if(k == j || k == i)
          continue;
        sum = map[dem] + arr[k];
        if(sum > result && sum <= gioihan)
          result = sum;
      }
      dem++;
    }
    -- ox;
  }

  return result;
}

int main() {
  int sophantu = 0, songuoichoi = 0, gioihan = 0;
  cin>>sophantu;
  while(sophantu-->0){
    cin>>songuoichoi;
    int i = 0;
    int arrCanNang[songuoichoi];
    for(; i<songuoichoi; ++i){
      cin>>arrCanNang[i];
    }
    cin>>gioihan;

    cout<<TimTongLonNhatCoGioiHan(arrCanNang, songuoichoi, gioihan)<<"\n";
  }
  return 0;
}

为简单起见,您可以创建矩阵[w1,w2,...,wn] x [w1,w2,...,wn],放入sum(Wi,Wj),foreach k并找到MAX sum( Wi,Wj)+ Wk。