zoukankan      html  css  js  c++  java
  • 动态规划之背包问题

      背包问题是一个经典的算法问题,可以用动态规划,贪心法,分支界限法等方法解决。问题描述:有n个物品,编号1,2,3,、、n,其中第 i 个物品重量为Wi 价值 Vi ,有一个容量为W的背包。在容量允许范围内,如何选择物品,可以得到最大的价值。(为了简单起见,假设物品的重量 Wi 和价值Vi 都是正数)

      今天主要说的是0、1背包问题,解法是动态规划。当然,对于另外两种问题也会有所介绍。

    问题分析:

      用动态规划解问题首先要有效的找出子问题,可以通过这个子问题得推得原问题的解,通常子问题的实质是和原问题相同的,只是规模上的缩小,也就是说子问题和原问题可以有相同的表示形式,问题可通过不断的缩小规模(一般都会有一个界限)能找到子问题的解。

      这个问题要求解的是能用背包带走的物品的最大价值。定义 m[i,w] 为:用第1,、2、3、、i 个物品装入质量<=W的背包的最大价值。

      m[i,w]的取值情况分析:

        1)m[0,\,w]=0  ,背包的质量为w,里面没有物品,所以它的价值为0;

        2)m[i,\,0]=0   ,背包质量为0,所以里面没法装任何东西, 不论前面的 i 是多少,总价值为0;

      对于任意的第 i 个物品,有两种情况,放进背包或者不放。不要第 i 个物品 如果w_i > w\,! 则:

        3)m[i,\,w]=m[i-1,\,w]因为第i 个物品的重量大于背包的容量,所以不可放入。

      如果w_i leqslant w. 那么

        4)m[i,\,w]=max(m[i-1,\,w],\,m[i-1,w-w_i]+v_i)  

      对于第 i 个物品,有两种可选择方案:如果放入背包中,那么 m[i,w]=m[i-1,w-wi]+vi。也就是i的前一个的最大值加上自己的价值。如果不要第i个物品,那么:m[i,w]=m[i-1,w]。也就是 i 的前一个的最大值。因为背包问题最后要取得最大的价值,所以就选这两种情况中价值最大的。

      在这个问题中,定义子问题: m[i,w] 对于每个子问题,都可通过上面的分析求出。通过3),4)可以发现,每一次求取子问题,问题的规模就被缩小。要么在w 上减小,要么在 i 上减小。最后问题的规模会被缩小为 m[i,0]和m[0,w].而这两个的值都为0,只要逆向思维反推回去,就能逐步得到问题的解。

    算法描述

    算法实现JAVA版

    public class Knapsack {
    	static int totalWeight = 10;
    	static int[] weight = new int[] { 2, 2, 6, 5, 4 };
    	static int[] vaule = new int[] { 6, 3, 5, 4, 6 };
    	static int[] x = new int[weight.length];
    	static int[][] matri = new int[weight.length + 1][totalWeight + 1];
    	static int[] has = new int[weight.length];
    
    	public static void knapsack() {
    		for (int i = 0; i <= totalWeight; i++) {
    			matri[0][i] = 0;
    		}
    		for (int i = 0; i <= weight.length; i++) {
    			matri[i][0] = 0;
    		}
    
    		for (int i = 1; i <= weight.length; i++) {
    			for (int j = 1; j <= totalWeight; j++) {
    				if (weight[i - 1] > j) {
    					matri[i][j] = matri[i - 1][j];
    				} else {
    					matri[i][j] = Math.max(matri[i - 1][j], matri[i - 1][j
    							- weight[i - 1]]
    							+ vaule[i - 1]);
    				}
    			}
    		}
    	}
    
    	public static void buildSolution() {
    		int j = totalWeight;
    		for (int i = weight.length; i >= 1; i--) {
    			if (matri[i][j] == matri[i - 1][j]) {
    				has[i - 1] = 0;
    
    			} else {
    				has[i - 1] = 1;
    				j = j - weight[i - 1];
    			}
    		}
    	}
    
    	public static void main(String[] args) {
    		knapsack();
    		buildSolution();
    		int sum = 0;
    		for (int i = 0; i < weight.length; i++) {
    			if (has[i] == 1) {
    				sum += vaule[i];
    				System.err.println(i);
    			}
    		}
    		System.out.println(sum);
    	}
    }
    
  • 相关阅读:
    后可视化编程
    查看图片前进后退效果图
    [置顶] 后可视化编程
    xCAT安装配置文档
    jQuery邮箱验证
    2011级csdnjava张侃—Spring(1)
    [置顶] 后可视化编程时代
    php中Session使用方法详解
    关于浏览器ip代理导致定位错乱问题的坑
    PHPStorm使用技巧及快捷键
  • 原文地址:https://www.cnblogs.com/wxgblogs/p/5721645.html
Copyright © 2011-2022 走看看