簡體   English   中英

背包 - 最低優先級,最小重量

[英]Knapsack - lowest priority, minimum weight

我必須實現背包問題的以下變化。 背包的每個項目都有優先權和重量。 現在我指定一個權重X.我必須知道計算權重總和至少為X且具有最低優先級的最小項目集。 每個項目只能選擇一次。 例:

    KnapsackItem a = new KnapsackItem("a", 1000, 0.1);
    KnapsackItem b = new KnapsackItem("b", 1000, 0.01);
    KnapsackItem c = new KnapsackItem("c", 1000, 0.01);

    Knapsack sack = new Knapsack(1900);
    sack.addItem(a);
    sack.addItem(b);
    sack.addItem(c);

    for (KnapsackItem item : sack.compute()) {
        System.out.println(item);
    }

這應該返回b,c。

我的解決方案返回b,a。 我不知道為什么。 花了幾個小時調試,但我只是沒有得到它。 也許有人可以查看或發布此問題變體的解決方案作為代碼。

public class Knapsack {
/**
 * The sum of the priorities. For example "prisoSum.get(2) returns 5" means,
 * that element 2 returns a sum priority of 5.
 */
private HashMap<Integer, Double> prioSum = new HashMap<Integer, Double>();

/**
 * List of items.
 */
private ArrayList<KnapsackItem> items;

/**
 * Minimum weight. The sum of the weights of the items in the item list must
 * at least be equal to this value.
 */
private int minWeight;

/**
 * Constructor.
 *
 * @param minWeight
 *            the minimum weight.
 */
public Knapsack(final int minWeight) {
    this.items = new ArrayList<KnapsackItem>();
    this.minWeight = minWeight;
}

/**
 * Computes the items to select.
 *
 * @return list of items to select.
 */
public final ArrayList<KnapsackItem> compute() {
    ArrayList<KnapsackItem> ret = new ArrayList<KnapsackItem>();
    int weightLeft = this.minWeight;
    KnapsackItem item;

    while (weightLeft > 0) {
        ArrayList<KnapsackItem> diff = getDifference(this.items, ret);
        if (diff.size() == 0) {
            break;
        }

        item = computeBestItemForMinVal(diff,
                weightLeft);

        ret.add(item);
        weightLeft -= item.getWeight();
    }

    return ret;
}

/**
 * Gets the best item to select for a given weight.
 *
 * @param list
 *            List of items to select form
 * @param minVal
 *            given weight
 * @return best item from list for given weight
 */
private KnapsackItem computeBestItemForMinVal(
        final ArrayList<KnapsackItem> list, final int minVal) {
    int[] best = new int[minVal + 1];
    for (int w = 0; w <= minVal; w++) {
        for (int i = 0; i < list.size(); i++) {
            KnapsackItem curIt = list.get(i);

            // Current priority inclusive all antecessors
            double curVal = 0;
            if (prioSum.get(w - curIt.getWeight()) != null) {
                curVal = prioSum.get(w - curIt.getWeight())
                        + curIt.getPriority();
            } else {
                curVal = 0 + curIt.getPriority();
            }
            if (prioSum.get(w) == null) {
                prioSum.put(w, curVal);
                best[w] = i;
            } else if (prioSum.get(w) > curVal) {
                prioSum.put(w, curVal);
                best[w] = i;
            }
        }
    }
    return list.get(best[minVal]);
}

/**
 * Computes the difference between two given list of Knapsack items and
 * returns it.
 *
 * @param main
 *            first list
 * @param sub
 *            second list
 * @return difference
 */
private ArrayList<KnapsackItem> getDifference(
        final ArrayList<KnapsackItem> main,
        final ArrayList<KnapsackItem> sub) {
    ArrayList<KnapsackItem> ret = new ArrayList<KnapsackItem>();

    for (int m = 0; m < main.size(); m++) {

        boolean found = false;
        for (int s = 0; s < sub.size(); s++) {
            if (main.get(m).getName() == sub.get(s).getName()) {
                found = true;
                break;
            }
        }

        if (!found) {
            ret.add(main.get(m));
        }
    }

    return ret;
}

}

我發現了自己的錯誤。 我必須添加prioSum.clear(); to computeBestItemForMinVal()。 因此,先前調用的數據將被刪除。 我現在也開始重量的for循環為1,而不是0:

private KnapsackItem computeBestItemForMinVal(
        final ArrayList<KnapsackItem> list, final int minVal) {
    int[] best = new int[minVal + 1];
    prioSum.clear();
    for (int w = 1; w <= minVal; w++) {
...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM