10.动态规划(3)——0-1背包问题

  在上一篇《9.动态规划(2)——子集和问题》中,谈到了什么是子集和问题,以及实现。背包问题实际也是子集和问题的一种,不过背包问题不是“判断问题”而是一个“最优问题”。而背包问题实际上又分为“0-1背包”,“完全背包”,本文对“0-1背包”进行讲解。

  问题:有n个物品,每个物品的重量为weigh[i],每个物品所对应的价值为price[i],现在有一个背包,背包所能承受的重量为W,问背包能装下的物品总价值最大是多少?

  定义s[i, j]表示前i个物品的总价值,j为背包的承重量。当j = W或者最接近于W且小于W时,此时就是问题的解。

  对于“动态规划”的关键就是要找到其递推公式,递推公式往往会将一个问题以某个值为边界拆分为两部分。背包问题的求解是子集和问题的最优化求解,在《9.动态规划(2)——子集和问题》中分析过递推公式的推导工程,在这里重新分析推导。

  分析:s[i, j]表示前i个物品,如果前i - 1个物品价值已经达到背包承重量j的极限,那么第i个物品就不能放进去(j - wi < 0),此时就可表示s[i, j] = s[i - 1, j]。但如果第i - 1个物品未达到背包承重量j的极限(j - wi >= 0),此时我们计算前i - 1个物品的价值就是s[i - 1, j - wi],此时加上第i个物品的价值就可以表示为s[i - 1, j - wi] + pi。

  综上得到递推公式:

  举例:物品的重量集合w = (2, 4, 1, 5, 3),物品的价格集合 p = (4, 5, 19, 3, 2),背包重量6。通过上面的递推公式,将这个背包问题利用矩阵来表示,第6列的最大值即为背包重量为6时的最大价值。

  Java

 1 package com.algorithm.dynamicprogramming;
 2
 3 import java.util.Arrays;
 4
 5 /**
 6  * 0-1背包问题
 7  *           | s[i - 1, j]                      (j - wi < 0)
 8  * s[i, j] = |     | s[i - 1, j]
 9  *           | Max |                            (j - wi >= 0)
10  *           |     | s[i - 1, j -wi] + pi
11  * Created by yulinfeng on 7/3/17.
12  */
13 public class KnapsackProblem {
14     public static void main(String[] args) {
15         int[] weight = {2, 4, 1, 5, 2};
16         int[] price = {4, 5, 19, 3, 2};
17         int knapsackWeight = 6;
18         int value = knapsackProblem(weight, price, knapsackWeight);
19         System.out.println(value);
20     }
21
22     /**
23      * 动态规划求解0-1背包问题
24      * @param weight 物品重量
25      * @param price 物品价值
26      * @param knapsackWeight 背包承重量
27      * @return
28      */
29     private static int knapsackProblem(int[] weight, int[] price, int knapsackWeight) {
30         int row = weight.length + 1;
31         int col = knapsackWeight + 1;
32         int[][] solutionMatrix = new int[row][col];
33         int[] values = new int[row];
34         values[0] = 0;
35         for (int i = 0; i < row; i++) {
36             solutionMatrix[i][0] = 0;
37         }
38         for (int j = 0; j < col; j++) {
39             solutionMatrix[0][j] = 0;
40         }
41
42         for (int i = 1; i < row; i++) {
43             for (int j = 1; j < col; j++) {
44                 solutionMatrix[i][j] = solutionMatrix[i - 1][j];
45                 if (j - weight[i - 1] >= 0 && solutionMatrix[i - 1][j - weight[i - 1]] + price[i - 1] > solutionMatrix[i][j]) {
46                     solutionMatrix[i][j] = solutionMatrix[i - 1][j - weight[i - 1]] + price[i - 1];
47                 }
48             }
49             values[i] = solutionMatrix[i][col - 1];
50         }
51         Arrays.sort(values);
52         return values[values.length - 1];
53     }
54 }

  Python3

 1 def knapsack_problem(weight, price, knapsackWeight):
 2     ‘‘‘
 3     0-1背包问题
 4               | s[i - 1, j]                      (j - wi < 0)
 5     s[i, j] = |     | s[i - 1, j]
 6               | Max |                            (j - wi >= 0)
 7               |     | s[i - 1, j -wi] + pi
 8
 9     Created by yulinfeng on 7/3/17.
10     ‘‘‘
11     row = len(weight) + 1
12     col = len(price) + 1
13     solutionMatrix = [[0 for c in range(col)] for r in range(row)]
14     values = [0] * row
15     for i in range(row):
16         solutionMatrix[0][i] = 0
17     for j in range(col):
18         solutionMatrix[j][0] = 0
19     for m in range(1, row):
20         for n in range(1, col):
21             solutionMatrix[m][n] = solutionMatrix[m - 1][n]
22             if n - weight[m - 1] >= 0 and solutionMatrix[m - 1][n - weight[m - 1]] + price[m - 1] > solutionMatrix[m][n]:
23                 solutionMatrix[m][n] = solutionMatrix[m - 1][n - weight[m - 1]] + price[m - 1]
24         values[m] = solutionMatrix[m][col - 1]
25
26     values.sort()
27     return values[len(values) - 1]
28
29 weight = (2, 4, 1, 5, 2)
30 price = (4, 5, 19, 3, 2)
31 knapsackWeight = 6
32 value = knapsack_problem(weight, price, knapsackWeight)
33 print(value)
时间: 2024-10-13 20:17:52

10.动态规划(3)——0-1背包问题的相关文章

基础算法(七)——动态规划【0/1背包问题】

首先,对于动态规划,我来做一个简短的介绍,相信各位都看得懂.动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数学方法.先给一道最简单的例题(小学奥数水平): 这就是一个模拟的动态规划法! 好了,现在开始认识一下最简单的动态规划实例:0/1背包. [问题描述]有一位旅行者要出远门,到商店里去筹备东西.在商店里,摆放了n样物品,每种物品有各自的体积,但是每种物品只有一件.这个旅行家有一个限制装V个体积的物品的背包,但是这

hdu2602Bone Collector ——动态规划(0/1背包问题)

Problem Description Many years ago , in Teddy’s hometown there was a man who was called “Bone Collector”. This man like to collect varies of bones , such as dog’s , cow’s , also he went to the grave …The bone collector had a big bag with a volume of

动态规划算法实现部分——0/1背包问题

代码: import java.util.*; import java.util.Scanner; /* *动态规划思想解决0/1背包问题 */ public class Main{ public static void main(String[] args){ Scanner in=new Scanner(System.in); System.out.println("输入背包的容量"); int bagCap=in.nextInt(); //背包的容量 System.out.pri

动态规划算法求解0,1背包问题

首先我们来看看动态规划的四个步骤: 1. 找出最优解的性质,并且刻画其结构特性: 2. 递归的定义最优解: 3. 以自底向上的方式刻画最优值: 4. 根据计算最优值时候得到的信息,构造最优解 其中改进的动态规划算法:备忘录法,是以自顶向下的方式刻画最优值,对于动态规划方法和备忘录方法,两者的使用情况如下: 一般来讲,当一个问题的所有子问题都至少要解一次时,使用动态规划算法比使用备忘录方法好.此时,动态规划算法没有任何多余的计算.同时,对于许多问题,常常可以利用其规则的表格存取方式,减少动态规划算

0/1背包问题与动态规划

假设背包容量M=9:(P1,P2,P3,P4,P5,P6)=(15,18,40,56,30,10);(W1,W2,W3,W4,W,5,W6)=(3,2,5,8,5,1). 算法思想 变量解释: F(i):Si中第一对序偶在数组中的位置(下标) l, h:Si-1的第一对序偶和最后一对序偶在数组中的位置,即F(i-1)和F(i)-1. k: Si-1中当前要加入Si的序偶的位置. u: 在Si-1能够产生Si1序偶的最后一个位置,即对于u+1<=v<= h的序偶(Pv,Wv),有Wv+wi>

0/1背包问题(回溯法)

回溯法是一个既带有系统性又带有跳跃性的搜索算法.它在包含问题的所有解的解空间树中,按深度优先策略,从根结点出发搜索解空间树.算法搜索至解空间树的任意一结点时,先判断该结点是否包含问题的解.如果肯定不包含,则跳过对该结点为根的子树搜索,逐层向其祖先结点回溯:否则 ,进入该子树,继续按深度优先策略搜索. 问题的解空间 用回溯法解问题时,应明确定义问题的解空间.问题的解空间至少包含问题的一个(最优)解.对于 n=3 时的 0/1 背包问题,可用一棵完全二叉树表示解空间,如图所示: 求解步骤 1)针对所

0/1背包问题的动态规划法求解 —— Java 实现

0/1背包问题的动态规划法求解,前人之述备矣,这里所做的工作,不过是自己根据理解实现了一遍,主要目的还是锻炼思维和编程能力,同时,也是为了增进对动态规划法机制的理解和掌握. 值得提及的一个问题是,在用 JAVA 实现时, 是按算法模型建模,还是用对象模型建模呢? 如果用算法模型,那么 背包的值.重量就直接存入二个数组里:如果用对象模型,则要对背包以及背包问题进行对象建模.思来想去,还是采用了对象模型,尽管心里感觉算法模型似乎更好一些.有时确实就是这样,对象模型虽然现在很主流,但也不是万能的,采用

背包问题:0/1背包问题 普通背包问题(贪心算法只适用于普通背包问题)

//sj和vj分别为第j项物品的体积和价值,W是总体积限制. //V[i,j]表示从前i项{u1,u2,…,un}中取出来的装入体积为j的背包的物品的最大价值. 第一种:0/1背包问题 最大化 ,受限于  1)若i=0或j=0,  V[i,j] = 0 2)若j<si, V[i,j] = V[i-1,j] 3)若i>0且j>=si, V[i,j] = Max{V[i-1,j],V[i-1,j-si]+vi} 第二种:背包问题:在选择物品i装入背包时,可以选择物品i的一部分,而不一定要全部

iOS 10 / Swift 3.0 / XCode 8 总结

1,iOS10 新增的privacy settings iOS10添加了新的权限控制范围 如果你尝试访问这些隐私数据时得到如下错误: > This app has crashed because it attempted to access privacy-sensitive > data without a usage description. The app's Info.plist must contain > an NSCameraUsageDescription key wit

hive-0.10.0-cdh4.3.0安装

1.我使用的Hadoop2.0-cdh4.3.0,对应hive配套版本hive-0.10.0-cdh4.3.0. 2.修改hive/conf下hive-site.xml文件,无则创建hive-site.xml,在底部添加如下内容: [html] view plaincopy <?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href=&