貪心算法_01揹包問題_Java實現

轉載請註明出處:http://blog.csdn.net/ljmingcom304/article/details/50310789
本文出自:【樑敬明的博客】

1.貪心算法

  什麼是貪心算法?是指在對問題進行求解時,總是做出當前看來是最好的選擇。也就是說,不從整體最優上加以考慮,所得出的結果僅僅是某種意義上的局部最優解。因此貪心算法不會對所有問題都能得到整體最優解,但對於很多問題能產生整體最優解或整體最優解的近似解。

2.01揹包問題  

  一個旅行者有一個最多能裝m公斤的揹包,現在有n中物品,每件的重量分別是W1、W2、……、Wn,每件物品的價值分別爲C1、C2、……、Cn, 需要將物品放入揹包中,要怎麼樣放才能保證揹包中物品的總價值最大?

3.算法分析  

  當遇到這樣的問題,我們可以換一種角度去思考,假設在一個100m3的房子裏面,現在要將房子裝滿,同時要保證放入的物品個數最多以及裝入的東西最重,現在身邊有鐵球和棉花,請問大家是放鐵球進去好呢還是放棉花進去好呢?顯而易見,放入鐵球進去是最優選擇。但是原因是什麼呢?很簡單,就是因爲鐵球的密度較大,相同體積的鐵球和棉花相比,鐵球更重。
  不過前提是放入第一個鐵球時,鐵球的體積V1小於等於100m3 ;放入第二個鐵球時,鐵球的體積V2 小於等於(100-V1)m3;……;放入第n個鐵球時,鐵球的體積小於等於(100- n1 Vn-1)m3 ,要是第n個鐵球的體積大於(100- n1 Vn-1)m3 ,還真是不如放點單位體積更輕的棉花進去,說的極端點就是所有鐵球的體積都大於100m3 ,還真不如隨便放入點棉花進去合算。所以總是放鐵球進去,不考慮是否放入棉花,容易產生閒置空間,最終會得不到最優選擇,可能只是最優選擇的近似選擇。
  現在再次回到揹包問題上,要使得揹包中可以獲得最大總價值的物品,參照鐵球的例子我們可以知道選擇單位重量下價值最高的物品放入爲最優選擇。但是由於物品不可分割,無法保證能將揹包剛好裝滿,最後閒置的容量無法將單位重量價值更高的物品放入,此時要是可以將單位重量價值相對低的物品放入,反而會讓揹包的總價值和單位重量的價值更高。假設現在揹包的剩餘總重量爲5kg,存在一個4kg價值爲4.5的物品,一個3kg價值爲3的物品,一個2kg價值爲2的物品,很顯然將3kg和2kg的物品放入揹包中所獲得的價值更高,雖然沒有4kg的物品單位重量的價值高。因此通過貪心算法求解01揹包的問題可能得不到問題的最優解,得到的是近似最優解的解。
  創建一個物品對象,分別存在價值、重量以及單位重量價值三種屬性。

public class Knapsack implements Comparable<Knapsack> {
    /** 物品重量 */
    private int weight;
    /** 物品價值 */
    private int value;
    /** 單位重量價值 */
    private int unitValue;

    public Knapsack(int weight, int value) {
        this.weight = weight;
        this.value = value;
        this.unitValue = (weight == 0) ? 0 : value / weight;
    }

    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;
    }

    public int getUnitValue() {
        return unitValue;
    }

    @Override
    public int compareTo(Knapsack snapsack) {
        int value = snapsack.unitValue;
        if (unitValue > value)
            return 1;
        if (unitValue < value)
            return -1;
        return 0;
    }

}
  按照貪心算法將物品放入揹包中。
public class TXSFProblem {
    // 現有的物品
    private Knapsack[] bags;
    // 揹包的總承重
    private int totalWeight;
    // 揹包最大總價值
    private int bestValue;

    public TXSFProblem(Knapsack[] bags, int totalWeight) {
        this.bags = bags;
        this.totalWeight = totalWeight;
        // 對揹包按單位重量價值從大到小排序
        Arrays.sort(bags, Collections.reverseOrder());
    }

    public void solve() {
        int tempWeight = totalWeight;

        for (int i = 0; i < bags.length; i++) {
            //判斷當前物品是否可以放入揹包中,若不能則繼續循環,查找下一個物品
            if (tempWeight - bags[i].getWeight() < 0)
                continue;

            tempWeight -= bags[i].getWeight();
            bestValue += bags[i].getValue();
        }
    }

    public int getBestValue() {
        return bestValue;
    }
}
  測試最終結果:85(實際最優結果爲90)
public class TXSFTest {

    public static void main(String[] args) {

        Knapsack[] bags = new Knapsack[] { new Knapsack(2, 13),
                new Knapsack(1, 10), new Knapsack(3, 24), new Knapsack(2, 15),
                new Knapsack(4, 28), new Knapsack(5, 33), new Knapsack(3, 20),
                new Knapsack(1, 8) };
        int totalWeight = 12;

        TXSFProblem problem = new TXSFProblem(bags, totalWeight);
        problem.solve();

        System.out.println(problem.getBestValue());
    }

}


 
  

發佈了39 篇原創文章 · 獲贊 14 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章