【问题标题】:Is this similar to knapsack or Change-making algorithm?这类似于背包或变革算法吗?
【发布时间】:2014-12-06 16:25:17
【问题描述】:

这个问题涉及到试图适应 不同的重量放入一个袋子中,这样袋子最终会带有一个 指定总重量或最接近指定总重量。

示例 1:- 袋子最多可容纳 240 公斤的重量

Item1- 60kg,Item2- 30kg,Item3- 55kg,Item4- 60kg,Item5- 80kg,Item6- 40kg,Item7- 7kg,

这里选择的项目应该是Item1、Item4、Item5和Item6(60+60+80+40 = 240 kg)

示例 2:- 袋子最多可容纳 180 公斤的重量

Item1- 60kg,Item2- 30kg,Item3- 55kg,Item4- 30kg,Item5- 70kg,Item6- 48kg

这里选择的项目应该是Item1、Item4、Item5和Item6(60+70+48 = 178 kg)

最接近180公斤

这是我的模板方法

public List getSelectedItems(List<Presentation> inputList, int knapsackCapacity){
List selectItems;

// optimized algorith  which returns selectItems and inputList containing  the 
//left out items i.e which are not selected;

return selectItems;
}

网上有些人称它为Knapsack problem 的最简单形式,因为它没有任何相关的利益/利润,有些人称它为Change-making problem

无论它属于哪个类别,我都无法获得此算法,因此无法从中制作 java 程序。这里有什么帮助吗?

【问题讨论】:

  • 背包很难。如果您可以“优化”其解决方案,那么您至少应该获得诺贝尔奖。可能还有一些间谍机构的暗杀……
  • @hop 你的意思是说递归是目前唯一的方法,直到有人提出更好的解决方案?
  • @MSach:不,我根本不想这么说。

标签: java algorithm knapsack-problem


【解决方案1】:

可以使用动态编程在伪多项式时间内 (O(nW)) 以最佳方式解决此问题。你需要做的是像这样修改 Knapsack 0/1 的解决方案:

if w[i] > W
    m[i,W] = m[i-1,W]
else if W - m[i-1, W] < W - m[i-1, W - w[i]] + w[i]
    m[i,W] = m[i-1,W]
else
    m[i-1, W - w[i]] + w[i]

其中W 是权重限制,w 是元素权重数组。不同之处在于您必须最小化W 与结果之间的差异,而不是最大化值的总和。

这里是wikipedia 解决方案,并进行了必要的修改:

// Input:
// Weights (stored in array w)
// Number of distinct items (n)
// Knapsack capacity (W)
for j from 0 to W do
  m[0, j] := 0  // Initialize to 0
end for 
for i from 1 to n do    // for every element in the array
  for j from 0 to W do  // for every possible weight
    if w[i] > j then    // if the element's weight is higher than the max
      m[i, j] := m[i-1, j]  // use the solution that excludes the element
    // else if the diff between the solution that excludes the element and max weight
    // is smaller than the one that uses it, use the former.
    else if (j - m[i-1, j]) < (j - m[i-1, j - w[i]] + w[i])
      m[i, j] := m[i-1, j]
    // else use the element's weight in the solution
    else
      m[i, j] := m[i-1, j - w[i]] + w[i]
    end if

二维数组m,是记忆表,在算法的最后,m[k, p]持有从0到k的元素的最佳解,最大权重p

编辑:我在C++ 中实现并测试了它,它应该很容易移植到Java:

template<typename T>
long Weight(const T& w, int size, const int W)
{
    vector<vector<int>> m(size+1, vector<int>(W+1, 0));

    for(int i = 1; i <= size; ++i)
    {
        for(int j = 0; j <= W; ++j)
        {
            if(w[i-1] > j)
            {
                m[i][j] = m[i-1][j];
            }
            else if((j - m[i-1][j]) < (j - (m[i-1][j - w[i-1]] + w[i-1])))
            {
                m[i][j] = m[i-1][j];
            }
            else
            {
                m[i][j] = m[i-1][j - w[i-1]] + w[i-1];
            }
        }
    }

    return m[size][W];
}

【讨论】:

  • 什么是 m ?如果你能解释一下这将是很大的帮助。
  • 在动态编程中,你总是需要一个记忆表来记录以前找到的解决方案,这就是m,你可以使用维度为Wn的二维数组,其中@ 987654339@ 是元素的数量。
  • 谢谢。我无法弄清楚你的算法在这里试图做什么。你能解释一下吗。提前致谢。我只是打破了我的头,但无法打破它的解决方案
  • mail.python.org/pipermail/python-list/2013-December/662545.html 的一些人甚至认为这不完全是背包问题,而是一个 Change-making_problem 问题,因为它没有相关的价值
  • imreal 我在sanfoundry.com/java-program-knapsack-algorithm 发现了 java 代码,但由于我只是权重约束,所以无法弄清楚如何从中消除价值约束。你能帮忙吗?
【解决方案2】:

我喜欢这个问题,所以只想分享我的方法

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


public class Test {

  public static void main(String[] args) {


    List<Presentation> l = new ArrayList<Presentation>();
    Presentation p1=new Presentation("one",20);
    Presentation p2=new Presentation("two",20);
    Presentation p3=new Presentation("three",20);
    Presentation p4=new Presentation("four",20);
    Presentation p5=new Presentation("five",20);
    Presentation p6=new Presentation("six",20);
    Presentation p7=new Presentation("seven",20);
    Presentation p8=new Presentation("eight",20);
    Presentation p9=new Presentation("nine",20); 
    Presentation p10=new Presentation("ten",90);
    Presentation p11=new Presentation("eleven",90);
    l.add(p1);
    l.add(p2);
    l.add(p3);
    l.add(p4);
    l.add(p5);
    l.add(p6);
    l.add(p6);
    l.add(p7);
    l.add(p8);
    l.add(p9);
    l.add(p10);
    l.add(p11);
    System.out.println(getSelectedItems(l,200));
  }

  private static List<String>  getSelectedItems(List<Presentation> l, int knapsackCapacity) {
    int sum=0;
    int temp=0;
    PresentationCompare compare=new PresentationCompare();
    List<String> s=new ArrayList<String>();
    while(sum!=knapsackCapacity && sum<knapsackCapacity && l.size()!=0){
      Presentation maxObj=Collections.max(l,compare);
      temp+=maxObj.getWeight();
      if(temp<=knapsackCapacity){
        sum=temp;
        s.add(maxObj.getName());
        l.remove(l.indexOf(maxObj));
      }else{
        l.remove(l.indexOf(maxObj));
        temp=sum;
      }
    }
    return s;
  }



}

import java.util.Comparator;


public class PresentationCompare implements Comparator<Presentation> {

  public int compare(Presentation o1, Presentation o2) {
    return o1.weight-o2.weight;
  }

}

【讨论】:

  • 你想在这里做什么?
  • 一个接一个地取最大值并添加直到总和我需要的东西或所有元素都被添加
【解决方案3】:

我同意虚幻分析。但这可以在不修改背包解决方案的情况下解决。只需考虑权重的值与权重相同。那我们就不用修改背包程序了。下面是例子

import java.util.ArrayList;
import java.util.List;
public class Knapsack {

    public static void main(String[] args) {

        int[] weight = {60, 30, 55, 60, 80, 40, 7};
        int[] value = {60, 30, 55, 60, 80, 40, 7};
        int targetSum = 31;

        knapsack(weight, value, targetSum);

    }

    public static void knapsack(int[] weight, int[] value, int targetSum) {

        int[][] weightValMatrix = new int[weight.length + 1][targetSum + 1];

        for (int i = 0; i < weight.length; i++) {
            for (int k = 0; k < targetSum + 1; k++) {
                weightValMatrix[i][k] = 0;
            }

        }

        for (int i = 1; i < weight.length + 1; i++) {
            for (int k = 1; k < targetSum + 1; k++) {
                if (k < weight[i - 1]) {
                    weightValMatrix[i][k] = weightValMatrix[i - 1][k];
                } else {
                    int valueInclusiveCurrentWeight = value[i - 1];
                    if ((k - weight[i - 1]) > 0) {
                        valueInclusiveCurrentWeight = valueInclusiveCurrentWeight
                                + weightValMatrix[i - 1][k - weight[i - 1]];
                    }

                    int valueExcludingCurrentWeight = weightValMatrix[i - 1][k];
                    weightValMatrix[i][k] = valueInclusiveCurrentWeight >= valueExcludingCurrentWeight ? valueInclusiveCurrentWeight
                            : valueExcludingCurrentWeight;

                }

            }



        }



        for (int i = 1; i < weight.length + 1; i++) {

            for (int k = 1; k < targetSum + 1; k++) {

                System.out.print(weightValMatrix[i][k]);

                if(k == targetSum){
                    System.out.println("");
                }
            }
        }


        System.out.println("final value is " + weightValMatrix[weight.length][targetSum]);

        List<Integer> finallySelectedWeightIndex = new ArrayList<Integer>();

        findActualWeightIndex(weightValMatrix, weight.length, targetSum, finallySelectedWeightIndex, weight);

        for(int index:finallySelectedWeightIndex){
            System.out.println("weight is " + weight[index-1] + " value is "+ value[index-1]);
        }


    }


    public static void findActualWeightIndex(int[][] weightValMatrix, int row, int column, 
            List<Integer> finallySelectedWeightIndex, int[] weight) {

        if(row==0 || column==0){
            return;
        }

        if(weightValMatrix[row][column]==weightValMatrix[row-1][column]){
            findActualWeightIndex(weightValMatrix, row-1, column, finallySelectedWeightIndex, weight);
        }else{
            finallySelectedWeightIndex.add(row);
            findActualWeightIndex(weightValMatrix, row-1, column - weight[row-1] , finallySelectedWeightIndex, weight);
        }
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-06
    • 2016-06-10
    • 2014-01-06
    • 2014-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-24
    相关资源
    最近更新 更多