4

そのため、ナップザックに 1 回 (0-1) しか入れられず、最大重量容量を持つ n 個のアイテム (私の場合は 4) の最適な組み合わせを見つけるアルゴリズムを生成しようとしています。おそらくより効果的に要約すると、合計値を最大化しながら重量が値 W 未満になるように、ナップザックに 4 つ以下の固有のアイテムを入れたいと考えています。私の最初の試みと仮定は、多次元のナップザックの問題に対して、すべてのアイテムのボリュームを 1 として、ボリューム制限を 4 にすることでした。しかし、私はそれが0-1ではないという問題に遭遇しました(バッグの中にあるかどうかを意味します)。次に、0-1(bounded) ナップサック コードを多次元化しようとしましたが、ボリューム制限と 0-1 要件を追加できませんでした。0-1 の多次元ナップザック問題をコーディングするにはどうすればよいですか? または、すべてのアイテムのボリュームを 1 として V のボリュームのみを保持するようにコードを調整するにはどうすればよいですか? コードは Java である必要はありませんが、それが私がこれまでに持っているものです。

ナップザック:

package hu.pj.alg;

import hu.pj.obj.Item;
import java.util.*;

public class ZeroOneKnapsack {

    protected List<Item> itemList  = new ArrayList<Item>();
    protected int maxWeight        = 0;
    protected int solutionWeight   = 0;
    protected int profit           = 0;
    protected boolean calculated   = false;

    public ZeroOneKnapsack() {}

    public ZeroOneKnapsack(int _maxWeight) {
        setMaxWeight(_maxWeight);
    }

    public ZeroOneKnapsack(List<Item> _itemList) {
        setItemList(_itemList);
    }

    public ZeroOneKnapsack(List<Item> _itemList, int _maxWeight) {
        setItemList(_itemList);
        setMaxWeight(_maxWeight);
    }

    // calculte the solution of 0-1 knapsack problem with dynamic method:
    public List<Item> calcSolution() {
        int n = itemList.size();

        setInitialStateForCalculation();
        if (n > 0  &&  maxWeight > 0) {
            List< List<Integer> > c = new ArrayList< List<Integer> >();
            List<Integer> curr = new ArrayList<Integer>();

            c.add(curr);
            for (int j = 0; j <= maxWeight; j++)
                curr.add(0);
            for (int i = 1; i <= n; i++) {
                List<Integer> prev = curr;
                c.add(curr = new ArrayList<Integer>());
                for (int j = 0; j <= maxWeight; j++) {
                    if (j > 0) {
                        int wH = itemList.get(i-1).getWeight();
                        curr.add(
                            (wH > j)
                            ?
                            prev.get(j)
                            :
                            Math.max(
                                prev.get(j),
                                itemList.get(i-1).getValue() + prev.get(j-wH)
                            )
                        );
                    } else {
                        curr.add(0);
                    }
                } // for (j...)
            } // for (i...)
            profit = curr.get(maxWeight);

            for (int i = n, j = maxWeight; i > 0  &&  j >= 0; i--) {
                int tempI   = c.get(i).get(j);
                int tempI_1 = c.get(i-1).get(j);
                if (
                    (i == 0  &&  tempI > 0)
                    ||
                    (i > 0  &&  tempI != tempI_1)
                )
                {
                    Item iH = itemList.get(i-1);
                    int  wH = iH.getWeight();
                    iH.setInKnapsack(1);
                    j -= wH;
                    solutionWeight += wH;
                }
            } // for()
            calculated = true;
        } // if()
        return itemList;
    }

    // add an item to the item list
    public void add(String name, int weight, int value) {
        if (name.equals(""))
            name = "" + (itemList.size() + 1);
        itemList.add(new Item(name, weight, value));
        setInitialStateForCalculation();
    }

    // add an item to the item list
    public void add(int weight, int value) {
        add("", weight, value); // the name will be "itemList.size() + 1"!
    }

    // remove an item from the item list
    public void remove(String name) {
        for (Iterator<Item> it = itemList.iterator(); it.hasNext(); ) {
            if (name.equals(it.next().getName())) {
                it.remove();
            }
        }
        setInitialStateForCalculation();
    }

    // remove all items from the item list
    public void removeAllItems() {
        itemList.clear();
        setInitialStateForCalculation();
    }

    public int getProfit() {
        if (!calculated)
            calcSolution();
        return profit;
    }

    public int getSolutionWeight() {return solutionWeight;}
    public boolean isCalculated() {return calculated;}
    public int getMaxWeight() {return maxWeight;}

    public void setMaxWeight(int _maxWeight) {
        maxWeight = Math.max(_maxWeight, 0);
    }

    public void setItemList(List<Item> _itemList) {
        if (_itemList != null) {
            itemList = _itemList;
            for (Item item : _itemList) {
                item.checkMembers();
            }
        }
    }

    // set the member with name "inKnapsack" by all items:
    private void setInKnapsackByAll(int inKnapsack) {
        for (Item item : itemList)
            if (inKnapsack > 0)
                item.setInKnapsack(1);
            else
                item.setInKnapsack(0);
    }

    // set the data members of class in the state of starting the calculation:
    protected void setInitialStateForCalculation() {
        setInKnapsackByAll(0);
        calculated     = false;
        profit         = 0;
        solutionWeight = 0;
    }

} // class

そしてアイテム:

package hu.pj.obj;

public class Item {

    protected String name    = "";
    protected int weight     = 0;
    protected int value      = 0;
    protected int bounding   = 1; // the maximal limit of item's pieces
    protected int inKnapsack = 0; // the pieces of item in solution

    public Item() {}

    public Item(Item item) {
        setName(item.name);
        setWeight(item.weight);
        setValue(item.value);
        setBounding(item.bounding);
    }

    public Item(int _weight, int _value) {
        setWeight(_weight);
        setValue(_value);
    }

    public Item(int _weight, int _value, int _bounding) {
        setWeight(_weight);
        setValue(_value);
        setBounding(_bounding);
    }

    public Item(String _name, int _weight, int _value) {
        setName(_name);
        setWeight(_weight);
        setValue(_value);
    }

    public Item(String _name, int _weight, int _value, int _bounding) {
        setName(_name);
        setWeight(_weight);
        setValue(_value);
        setBounding(_bounding);
    }

    public void setName(String _name) {name = _name;}
    public void setWeight(int _weight) {weight = Math.max(_weight, 0);}
    public void setValue(int _value) {value = Math.max(_value, 0);}

    public void setInKnapsack(int _inKnapsack) {
        inKnapsack = Math.min(getBounding(), Math.max(_inKnapsack, 0));
    }

    public void setBounding(int _bounding) {
        bounding = Math.max(_bounding, 0);
        if (bounding == 0)
            inKnapsack = 0;
    }

    public void checkMembers() {
        setWeight(weight);
        setValue(value);
        setBounding(bounding);
        setInKnapsack(inKnapsack);
    }

    public String getName() {return name;}
    public int getWeight() {return weight;}
    public int getValue() {return value;}
    public int getInKnapsack() {return inKnapsack;}
    public int getBounding() {return bounding;}

} // class
4

1 に答える 1

7

これは、2 つの次元 (サイズとボリューム) を持つナップザック 0-1 問題を解決するための一般的な実装です。はるかに簡単なので、リストのリストの代わりにマトリックスを使用しました。これは、クラス全体と、それをテストするためのメイン メソッドです。
次元を追加するには、マトリックスに新しい次元を追加し、内部サイクルを追加してすべての条件をチェックします。

public class MultidimensionalKnapsack {

    /** The size of the knapsack */
    private static int size;
    /** The volume of the knapsack */
    private static int vol;

    private static class Item {
        public int value;
        public int size;
        public int volume;
        public Item(int v, int w, int vol) {
            value = v;
            size = w;
            volume = vol;
        }
    }

    // Knapsack 0/1 without repetition
    // Row: problem having only the first i items
    // Col: problem having a knapsack of size j
    // Third dimension: problem having a knapsack of volume h
    private static int[][][] dynNoRep;

    private static void noRep(Item[] items) {
        dynNoRep = new int[items.length + 1][size + 1][vol + 1];
        for(int j = 0; j <= size; j++) {
            dynNoRep[0][j][0] = 0;
        }
        for(int i = 0; i <= vol; i++) {
            dynNoRep[0][0][i] = 0;
        }
        for(int i = 0; i <= items.length; i++) {
            dynNoRep[i][0][0] = 0;
        }
        for(int i = 1; i <= items.length; i++)
            for(int j = 0; j <= size; j++) {
                for(int h = 0; h <= vol; h++) {
                    if(items[i - 1].size > j)
                        // If the item i is too big, I  can't put it and the solution is the same of the problem with i - 1 items
                        dynNoRep[i][j][h] = dynNoRep[i - 1][j][h];  
                else {
                    if(items[i - 1].volume > h)
                        // If the item i is too voluminous, I can't put it and the solution is the same of the problem with i - 1 items
                        dynNoRep[i][j][h] = dynNoRep[i - 1][j][h];
                    else {
                        // The item i could be useless and the solution is the same of the problem with i - 1 items, or it could be 
                        // useful and the solution is "(solution of knapsack of size j - item[i].size and volume h - item[i].volume) + item[i].value" 
                        dynNoRep[i][j][h] = Math.max(dynNoRep[i - 1][j][h], dynNoRep[i - 1][j - items[i - 1].size][h - items[i - 1].volume] + items[i - 1].value);
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
        size = 15;
        vol = 12;
        Item[] items = {new Item(2, 4, 1), new Item(1, 5, 4), new Item(6, 3, 9), 
            new Item(3, 3, 19), new Item(7, 2, 7), new Item(1, 2, 6), new Item(2, 1, 2),
            new Item(10, 9, 12), new Item(9, 10, 2), new Item(24, 23, 11)};
        System.out.print("We have the following " + items.length + " items (value, size, volume): ");
        for(int i = 0; i < items.length; i++)
            System.out.print("(" + items[i].value + ", " + items[i].size + ", " + items[i].volume + ") ");
        System.out.println();
        System.out.println("And a knapsack of size " + size + " and volume " + vol);

        noRep(items);
        System.out.println();
        // Print the solution
        int j = size, h = vol, finalSize = 0, finalValue = 0, finalVolume = 0;
        System.out.print("Items picked (value, size, volume) for 0/1 problems without repetitions: ");
        for(int i = items.length; i > 0; i--) {
            if(dynNoRep[i][j][h] != dynNoRep[i - 1][j][h]) {
                System.out.print("(" + items[i - 1].value + ", " + items[i - 1].size + ", " + items[i - 1].volume + ") ");
                finalSize += items[i - 1].size;
                finalValue += items[i - 1].value;
                finalVolume += items[i - 1].volume;
                j -= items[i - 1].size;
                h -= items[i - 1].volume;
            }
        }
        System.out.println();
        System.out.println(" Final size: " + finalSize);
        System.out.println(" Final volume: " + finalVolume);
        System.out.println(" Final value: " + finalValue);
    }

}

于 2013-01-20T00:43:12.010 に答える