算法-01揹包2

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.junit.Test;

/**
 * 有n個物品,第i(1<=i<=n)個物品的價值爲Vi,重量爲Wi,揹包容量爲sackWeight,考慮<b>如何選擇裝入揹包的物品</b>,
 * 使得裝入揹包的物品的<b>總價值最大</b>。
 * 選擇放入物品到揹包,此時記作 Xi = 1,否則記 Xi = 0;則經過若干選擇後形成行向量(X1, X2, X3, X4, ...Xi, ...)
 * 假設放入第i個物品,放入後達到總價值最大,
 * C[i,j]表示揹包重量爲j,現有i個物品裝入包中,物品編號依次是1,2,3,4,5,6...i...,從i個物品中選擇,使得揹包中物品的價值最大
 * 當j==0時候,i個物品中一個都不能選擇
 * 當j==1時候,
 * <b>難點在於如何用編碼表示選擇第i個物品放入揹包,放入與不放入怎麼用代碼體現</b>
 * 用totalSize表示物品個數
 */

/**
 * 
 * knapsack類表示揹包
 *
 */
class Item{

    private int weight;//wu
    private int value;

    public Item(int weight, int value){
        this.weight = weight;
        this.value = value;
    }
    public int getWeight() {
        return weight;
    }
    public void setWeight(int weight) {
        this.weight = weight;
    }
    public int getValue() {
        return value;
    }
    public void setValue(int value) {
        this.value = value;
    }

    @Override
    public String toString(){
        return "Item[weight=" + weight + ", value=" + value + "]";
    }

}

public class KnapsackDemo {

    @Test
    public void test(){
        //int itemSize = 5;//有5個物品
        int sackWeight = 17;//揹包可以接受的總重量是16
        List<Item> items = new ArrayList<Item>();
        items.add(new Item(1, 1));
        items.add(new Item(1, 2));
        items.add(new Item(2, 2));
        items.add(new Item(4, 10));
        items.add(new Item(12, 4));

//      items.add(new Item(3, 4));
//      items.add(new Item(4, 5));
//      items.add(new Item(7, 10));
//      //items.add(new Item(4, 10));
//      items.add(new Item(8, 11));
//      items.add(new Item(9, 13));
        //int[] w = 
        //Item[] item
        //int values1 = solve( sackWeight, items);
        int values2 = solve2( sackWeight, items);
        //System.out.println("this is values1" + values1);
        System.out.println("this is values2" + values2);

        //
    }

    public int solve(int sackWeight, List<Item> items){
        int itemSize = items.size();
        //定義一個二維數組
        int [][] c = new int[itemSize + 1][sackWeight + 1];
        int totalValue = 0;
//      while(true){
//          
//      }
//      while(true){
//          
//      }
        for(int i = 0; i <= items.size(); i++){
            Item item = items.get(i);
            int weight = item.getWeight();
            int value = item.getValue();

            for(int j = 0; j<= sackWeight ; j++){

                if(i==0 || j==0){
                //if(j==0){
                    c[i][j] = 0;
                    totalValue = c[i][j] = 0;
                    //return totalValue;
                    // System.out.println(0);
                    System.out.println("i="+i+", c["+i+"]["+j+"] =" + c[i][j]);
                }else{

                     //if(weight > j & i>= 1){
                    if(weight > j ){
                         //標號爲i的物品不放人揹包,且此時揹包中的物品的價值總和達到最大
                         //還有一種情況是重量超了,放不下該物品
                        // c[i][j] = c[i-1][j]; //重量超了,放不下該物品
                         c[i][j] = c[i-1][j]; 
                         totalValue =  c[i][j];
                         System.out.println("i="+i+", c["+i+"]["+j+"] =" + c[i][j]);
                        // System.out.println(c[i][j]);
                        // return totalValue;
                     }else{
                            //標號爲i的物品不放人揹包,且此時揹包中的物品的價值總和達到最大
                            // c[i][j] = c[i-1][j];
                             //標號爲i的物品放入揹包
                            // c[i][j] = c[i-1][(sackWeight - w[i])] + v[j];
                             c[i][j] = Math.max(c[i-1][(j - weight)] + value, c[i-1][j]);
                             //if()
                             if(c[i][j] > c[i-1][j]){
                                 System.out.println("choose"+ i);
                             }


                             System.out.println("i="+i+", c["+i+"]["+j+"] =" + c[i][j]);
                     }
                     totalValue = c[i][j];
                }

             }
            //return totalValue;
        }
        return totalValue;
    }

     public int solve2(int sackWeight, List<Item> items) {
         int itemSize = items.size();
         int [][] bestValues = new int[itemSize + 1][sackWeight + 1];
            int bestValue = 0;
            // 遍歷揹包的承重
            for (int j = 0; j <= sackWeight; j++) {
                // 遍歷指定物品
                for (int i = 0; i <= itemSize; i++) {
                    // 當揹包不放入物品或承重爲0時,其最大價值均爲0
                    if (i == 0 || j == 0) {
                        bestValues[i][j] = 0;
                    } else {
                        // 如果第 i個物品重量大於總承重,則最優解存在於前 i-1 個揹包中
                        if (j < items.get(i-1).getWeight()) {
                            bestValues[i][j] = bestValues[i - 1][j];
                        } else {
                            // 如果第 i個物品不大於總承重,則最優解要麼是包含第 i個揹包的最優解,
                            // 要麼是不包含第 i個揹包的最優解, 取兩者最大值
                           // int weight = bags[i - 1].getWeight();
                            int weight = items.get(i-1).getWeight();
                            int value = items.get(i-1).getValue();
                            bestValues[i][j] = Math.max(bestValues[i - 1][j], value
                                    + bestValues[i - 1][j - weight]);
                        }
                    }
                }
            }

            return bestValue = bestValues[itemSize][sackWeight];
        }

//      public int getBestValue() {
//          return bestValue;
//      }
}
發佈了142 篇原創文章 · 獲贊 34 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章