码迷,mamicode.com
首页 > 其他好文 > 详细

学习日志---动态规划(背包问题)

时间:2015-09-21 01:51:53      阅读:203      评论:0      收藏:0      [点我收藏+]

标签:java算法

背包问题:

利用动态矩阵的方式,一步一步在前一次有最优解的时候,推断后面的最优解

核心:

bestValues[i][j] = Math.max(bestValues[i - 1][j],
                                ivalue + bestValues[i - 1][j - iweight]);

i是指商品,[i]是指前i个,v是指背包可容纳的重量,节点值是指最优的价值数。

因为加了一个i,最优解要么就是有i,要么就是没有i。

摘自:http://www.cnblogs.com/bourbon/archive/2011/08/23/2151044.html

如果一个问题的最优解包含了物品n,即Xn = 1,那么其余X1, X2, .....,Xn-1 一定构成子问题1,2,.....,n-1在容量C - cn时的最优解。如果这个最优解不包含物品n,即Xn = 0;

那么其余 X1, X2.....Xn-1一定构成了子问题 1,2,....n-1在容量C时的最优解。 

 //请各位仔细品味这几句话

//物品类
public class Knapsack {

    /** 物品重量 */
    private int weight;

    /** 物品价值 */
    private int value;

    /***
     * 构造器
     */
    public Knapsack(int weight, int value) {
        this.value = value;
        this.weight = weight;
    }

    public int getWeight() {
        return weight;
    }

    public int getValue() {
        return value;
    }

    public String toString() {
        return "[weight: " + weight + " " + "value: " + value + "]";
    }
}

import java.util.ArrayList;

//背包算法类
public class KnapsackProblem {

    /** 指定背包 */
    private Knapsack[] bags;

    /** 总承重 */
    private int totalWeight;

    /** 给定背包数量 */
    private int n;

    /** 前 n 个背包,总承重为 totalWeight 的最优值矩阵 */
    private int[][] bestValues;

    /** 前 n 个背包,总承重为 totalWeight 的最优值 */
    private int bestValue;

    /** 前 n 个背包,总承重为 totalWeight 的最优解的物品组成 */
    private ArrayList<Knapsack> bestSolution;

    public KnapsackProblem(Knapsack[] bags, int totalWeight) {
        this.bags = bags;
        this.totalWeight = totalWeight;
        this.n = bags.length;
        if (bestValues == null) {
            bestValues = new int[n + 1][totalWeight + 1];
        }
    }

    /**
     * 求解前 n 个背包、给定总承重为 totalWeight 下的背包问题
     * 
     */
    public void solve() {

        System.out.println("给定背包:");
        for (Knapsack b : bags) {
            System.out.println(b);
        }
        System.out.println("给定总承重: " + totalWeight);

        // 求解最优值
        for (int j = 0; j <= totalWeight; j++) {
            for (int i = 0; i <= n; i++) {

                if (i == 0 || j == 0) {
                    bestValues[i][j] = 0;
                } else {
                    // 如果第 i 个背包重量大于总承重,则最优解存在于前 i-1 个背包中,
                    // 注意:第 i 个背包是 bags[i-1]
                    if (j < bags[i - 1].getWeight()) {
                        bestValues[i][j] = bestValues[i - 1][j];
                    } else {
                        // 如果第 i 个背包不大于总承重,则最优解要么是包含第 i 个背包的最优解,
                        // 要么是不包含第 i 个背包的最优解, 取两者最大值,这里采用了分类讨论法
                        // 第 i 个背包的重量 iweight 和价值 ivalue
                        int iweight = bags[i - 1].getWeight();
                        int ivalue = bags[i - 1].getValue();
                        bestValues[i][j] = Math.max(bestValues[i - 1][j],
                                ivalue + bestValues[i - 1][j - iweight]);
                    } // else
                } // else
            } // for
        } // for

        // 求解背包组成
        //这里是从矩阵中找最优的包裹,从后面开始找
        if (bestSolution == null) {
            bestSolution = new ArrayList<Knapsack>();
        }
        int tempWeight = totalWeight;
        for (int i = n; i >= 1; i--) {
            if (bestValues[i][tempWeight] > bestValues[i - 1][tempWeight]) {
                bestSolution.add(bags[i - 1]); // bags[i-1] 表示第 i 个背包
                tempWeight -= bags[i - 1].getWeight();
            }
            if (tempWeight == 0) {
                break;
            }
        }
        bestValue = bestValues[n][totalWeight];
    }

    /**
     * 获得前 n 个背包, 总承重为 totalWeight 的背包问题的最优解值 调用条件: 必须先调用 solve 方法
     * 
     */
    public int getBestValue() {
        return bestValue;
    }

    /**
     * 获得前 n 个背包, 总承重为 totalWeight 的背包问题的最优解值矩阵 调用条件: 必须先调用 solve 方法
     * 
     */
    public int[][] getBestValues() {

        return bestValues;
    }

    /**
     * 获得前 n 个背包, 总承重为 totalWeight 的背包问题的最优解值矩阵 调用条件: 必须先调用 solve 方法
     * 
     */
    public ArrayList<Knapsack> getBestSolution() {
        return bestSolution;
    }

}

public class KnapsackTest {

    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;
        KnapsackProblem kp = new KnapsackProblem(bags, totalWeight);

        kp.solve();
        System.out.println(" -------- 该背包问题实例的解: --------- ");
        System.out.println("最优值:" + kp.getBestValue());
        System.out.println("最优解【选取的背包】: ");
        System.out.println(kp.getBestSolution());
        System.out.println("最优值矩阵:");
        int[][] bestValues = kp.getBestValues();
        for (int i = 0; i < bestValues.length; i++) {
            for (int j = 0; j < bestValues[i].length; j++) {
                System.out.printf("%-5d", bestValues[i][j]);
            }
            System.out.println();
        }
    }
}


学习日志---动态规划(背包问题)

标签:java算法

原文地址:http://wukong0716.blog.51cto.com/10442773/1696527

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!