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

动态规划-01背包问题

时间:2019-05-22 19:04:47      阅读:103      评论:0      收藏:0      [点我收藏+]

标签:开始   问题:   rgs   mic   mamicode   多次   生成   01背包问题   code   

算法思想:动态规划
实际问题:01背包问题
编写语言:Java


问题描述

给定n种物品和一个背包,物品i的重量为wi,其价值是vi,背包的容量为c,问应如何向背包装入物品,使得背包中的物品价值最大。每个物品拿取或者不拿两种选择。不能选择装入某物品的一部分,也不能装入同一物品多次。

递归结构

声明一个大小为m[n][c]的二维数组,m[i][j]表示在面对第i件物品,且背包容量为j时所能获得的最大价值。则:

  1. m[i][j]=m[i-1][j],j<w[i]。其表示:背包容量不足以放下第i件物品,只能选择不拿。
  2. m[i][j]=max{m[i-1][j], m[i-1][j-wi]+vi},j>=w[i]。其表示:这时背包容量可以放下第i件物品,我们就要考虑拿这件物品是否能获取更大的价值。前者表示不装第i件物品的最大价值,后者表示装了第i件物品的最大价值,并为第i件物品预留了wi的容量。
Java代码
public class OneZeroKnapsackProblem
{
    public static void main(String[] args)
    {
        //以下数组第0位(第0行,第0列)都不存储数据
        int[] v = new int[]{0, 8, 10, 6, 3, 7, 2}; //每件物品的价值
        int[] w = new int[]{0, 4, 6, 2, 2, 5, 1}; //每件物品的重量
        int c = 12; //背包的容量
        int n = v.length - 1; //物品的数量
        int[][] m = new int[n + 1][c + 1]; //总价值数组
        int[] r = new int[n + 1]; //构造最优解的数组
        
        for(int i = 0; i <= n; i++)
        {
            for(int j = 0; j <= c; j++)
                m[i][j] = 0;
            r[i] = 0;
        }
        
        knapsack(v, w, c, n, m);
        traceback(m, w, c, n, r);
        
        System.out.println("物品数量为 " + n + " ,背包容量为 " + c);
        
        System.out.print("各个物品的价值为:");
        for(int i = 1; i <= n; i++)
        {
            System.out.print(v[i] + " ");
        }
        System.out.println();
        
        System.out.print("各个物品的重量为:");
        for(int i = 1; i <= n; i++)
        {
            System.out.print(w[i] + " ");
        }
        System.out.println();
        
        System.out.println("最多价值为:" + m[n][c]);
        
        System.out.print("放入的物品为:");
        for(int i = 1; i <= n; i++)
            System.out.print(r[i] + " ");
        System.out.println();
    }
    
    /**
      * 该方法计算最优解:
      * @param v 存储每个物品的价值
      * @param w 存储每个物品的重量
      * @param c 存储背包容量
      * @param n 物品数量
      * @param m 存储构造的最优解
    */
    public static void knapsack(int[] v, int[] w, int c, int n, int[][] m)
    {
        //物品从第1件物品开始计算
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= c; j++)
            {
                if(j >= w[i])
                {
                    m[i][j] = max(m[i - 1][j], m[i - 1][j - w[i]] + v[i]);
                }
                else
                {
                    m[i][j] = m[i - 1][j];
                }
            }
        }
    }
    
    /**
      * 该方法构造最优解的生成过程:
      * @param m 存储最优解的数组
      * @param w 存储每个物品的重量
      * @param c 存储背包容量
      * @param n 物品数量
      * @param x 存储最优解生成过程的数组
    */
    public static void traceback(int[][] m, int[] w, int c, int n, int[] x)
    {
        for(int i = 1; i <= n; i++)
        {
            if(m[i][c] == m[i - 1][c]) //第i件物品为未放入
            {
                x[i] = 0;
            }
            else //第i件放入
            {
                x[i] = 1;
                c -= w[i];
            }
        }
    }
    
    public static int max(int a, int b)
    {
        return a > b ? a : b;
    }
}
运行结果

技术图片

动态规划-01背包问题

标签:开始   问题:   rgs   mic   mamicode   多次   生成   01背包问题   code   

原文地址:https://www.cnblogs.com/wellsherish/p/10907730.html

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