動態規劃_01揹包問題_Java實現

原文地址:http://blog.csdn.net/ljmingcom304/article/details/50328141
本文出自:【梁敬明的博客】java

1.動態規劃  

  什麼是動態規劃?動態規劃就是將一個大問題不斷向下拆分紅小問題,直到拆分出的小問題能夠求出其解,而後將小問題的解不斷的向上合併,最終獲得大問題的解決方案。面試

2.揹包問題  

  一個旅行者有一個最多能裝m公斤的揹包,如今有n中物品,每件的重量分別是W一、W二、……、Wn,每件物品的價值分別爲C一、C二、……、Cn, 須要將物品放入揹包中,要怎麼樣放才能保證揹包中物品的總價值最大?算法

3.算法分析

  假設前n個物品,總承重爲j,物品的重量爲w,其最大價值爲v[n,j]。
  在揹包的總承重不變的前提下,一個物品是否放入揹包中直接影響到後面的物品是否能放入到揹包中,即一個物品很重同事物品價值又很低時,若裝入揹包中直接致使其餘更多的物品沒法放入揹包中,從而使得揹包中的最大總價值變低。
  當揹包的承重爲0,或者不將物品放入揹包時,揹包中的最大總價值均爲0,即v[n,0]=v[0,n]=0。
  放入當前物品n超過揹包的最大承重時,則沒法將該物品放入揹包中,即v[n,j]=v[n-1,j]。 
  放入當前物品n不超過揹包的最大承重時,則當前物品放入揹包時的最大價值爲vn+v[n-1,j-wn],不放入揹包時的最大價值爲v[n-1,j],所以對於當前物品是否放入揹包中所能得到的最大價值爲v[n,j]=max{ v[n-1,j],vn+v[n-1,j-wn] }。 
動態規劃
動態規劃
  上表從上往下,由左至右依次遍歷。假設F3的揹包承重爲3,此時物品的重量爲4,因此該物品沒法放入揹包中,此時揹包能夠得到的最大總價值爲E3的最大總價值25。假設E10的揹包承重爲10,此時物品的重量爲4,因此該物品能夠放入揹包中,當該物品不放入揹包中時,揹包的價值爲D10的最大價值62,放入揹包中時揹包的價值爲D6的最大價值加上該物品的價值,結果爲77,所以最終得出E10的最大價值爲77。
  建立物品對象,存在重量和價值兩種屬性。數組

public class Knapsack{
    /** 物品重量 */
    private int weight;
    /** 物品價值 */
    private int value;

    public Knapsack(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;
    }

}

 按照動態規劃算法將物品放入揹包中。微信

public class DTGHProblem {

    // 全部的物品
    private Knapsack[] bags;
    // 物品的數量
    private int n;
    // 揹包總承重
    private int totalWeight;
    // 第一維:當前第幾個物品;第二維:當前的揹包承重;值:當前揹包最大價值
    private int[][] bestValues;
    // 最終揹包中最大價值
    private int bestValue;

    public DTGHProblem(Knapsack[] bags, int totalWeight) {
        this.bags = bags;
        this.totalWeight = totalWeight;
        this.n = bags.length;
        if (bestValues == null) {
            // 考慮0的狀態+1,防止數組角標越界
            bestValues = new int[n + 1][totalWeight + 1];
        }
    }

    public void solve() {
        // 遍歷揹包的承重
        for (int j = 0; j <= totalWeight; j++) {
            // 遍歷指定物品
            for (int i = 0; i <= n; i++) {
                // 當揹包不放入物品或承重爲0時,其最大價值均爲0
                if (i == 0 || j == 0) {
                    bestValues[i][j] = 0;
                } else {
                    // 若是第 i個物品重量大於總承重,則最優解存在於前 i-1 個揹包中
                    if (j < bags[i - 1].getWeight()) {
                        bestValues[i][j] = bestValues[i - 1][j];
                    } else {
                        // 若是第 i個物品不大於總承重,則最優解要麼是包含第 i個揹包的最優解,
                        // 要麼是不包含第 i個揹包的最優解, 取二者最大值
                        int weight = bags[i - 1].getWeight();
                        int value = bags[i - 1].getValue();
                        bestValues[i][j] = Math.max(bestValues[i - 1][j], value
                                + bestValues[i - 1][j - weight]);
                    }
                }
            }
        }

        bestValue = bestValues[n][totalWeight];
    }

    public int getBestValue() {
        return bestValue;
    }

}

最終測試結果:90學習

public class DTGHTest {
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;
    DTGHProblem problem = new DTGHProblem(bags, totalWeight);

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

歡迎關注個人微信公衆號:「」Java面試通關手冊(堅持原創,分享美文,分享各類Java學習資源,面試題,以及企業級Java實戰項目回覆關鍵字免費領取):
微信公衆號測試

相關文章
相關標籤/搜索