动态规划_0-1背包问题

/**
 * 动态规划_0-1背包问题
 * @author Matt
 */
public class Knapsack {

    /**
     * 求得最优值
     * @param v 物品价值数组
     * @param w 物品质量数组
     * @param c 背包容量 
     * @param m 最优值数组
     */
    public static void knapsack(int []v, int []w, int c, int [][]m) {
        int n = v.length - 1; // 物品的数量
        // 先对最后一个物品进行取舍,得到基础值
        // 将最后一个物品的质量和背包容量进行比较,取较小值
        int jMax = Math.min(w[n]-1, c); 
        for (int j = 0; j <= jMax; j++) { // 背包容量小于物品质量则不装入
            m[n][j] = 0; // 不装入则价值为0
        }
        for (int j = w[n]; j <= c; j++) { // 物品质量大于背包质量则装入
            m[n][j] = v[n]; // 装入则价值为当前物品的价值v[n]
        }
        // 对2~n-1个物品进行判断选取
        for (int i = n - 1; i > 1; i--) {
            jMax = Math.min(w[i]-1, c);
            // 背包容量小于当前物品的质量则不装入
            for (int j = 0; j <= jMax; j++) { 
                m[i][j] = m[i+1][j];
            }
            // 背包容量大于当前物品的质量
            for (int j = w[i]; j <= c; j++) {
                // 对不装入和装入的两种情况取价值高者
                m[i][j] = Math.max(m[i+1][j], m[i+1][j-w[i]] + v[i]);
            }
            // 最后对第一个物品进行取舍
            m[1][c] = m[2][c];
            if (c >= w[1]) {
                // 求得的m[1][c]即为最优值
                m[1][c] = Math.max(m[1][c], m[2][c-w[1]] + v[1]);
            }
        }
    }

    /**
     * 最优解路径
     * @param m 最优值数组
     * @param w 质量数组
     * @param c 背包容量
     * @param x 是否拿取数组
     */
    public static void traceback(int [][]m, int []w, int c, int []x) {
        int n = w.length - 1; // 物品的个数
        // 对m数组从第一个物品到n-1个物品进行遍历
        for (int i = 1; i < n; i++) {
            // 如果没有装取,x[i]置0表示没有装取
            if (m[i][c] == m[i+1][c]) x[i] = 0;
            else { // 只有两种情况,不装或装,x[i]置1表示装取物品
                x[i] = 1;
                c -= w[i]; // 装取则容量减去当前物品的质量
            }
            x[n] = (m[n][c] > 0) ? 1 : 0; // 对最后一个物品进行判断
        }
    }

    public static void main(String[] args) {
        int []v = {0, 6, 3, 5, 4, 6};
        int []w = {0, 2, 2, 6, 5, 4};
        int c = 10;
        int [][]m = new int[7][11];
        int []x = new int[7];
        knapsack(v, w, c, m);
        traceback(m, w, c, x);
        System.out.println("Value: " + m[1][c]);
        System.out.print("Trace: ");
        for (int i = 0; i < x.length; i++) {
            System.out.print(x[i]);
        }
    }
}
// 运算结果:
//  Value: 15
//  Trace: 0110010
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值