赞
踩
01背包是在M件物品取出若干件放在空间为W的背包里,每件物品的体积为W1,W2至Wn,与之相对应的价值为P1,P2至Pn。01背包是背包问题中最简单的问题。01背包的约束条件是给定几种物品,每种物品有且只有一个,并且有权值和体积两个属性。在01背包问题中,因为每种物品只有一个,对于每个物品只需要考虑选与不选两种情况。如果不选择将其放入背包中,则不需要处理。如果选择将其放入背包中,由于不清楚之前放入的物品占据了多大的空间,需要枚举将这个物品放入背包后可能占据背包空间的所有情况。
01背包问题可以看作是决策一个序列(x1, x2, …, xn),对任一变量xi的决策是决定xi=1还是xi=0。在对xi-1决策后,已确定了(x1, …, xi-1),在决策xi时,问题处于下列两种状态之一:
(1)背包容量不足以装入物品i,则xi=0,背包不增加价值;
(2)背包容量可以装入物品i。
在(2)的状态下,物品i有两种情况,装入(则xi=1)或不装入(则xi=0)。在这两种情况下背包价值的最大者应该是对xi决策后的背包价值。
令V(i, j)表示在前i(1≤i≤n)个物品中能够装入容量为j(1≤j≤C)的背包中的物品的最大值,则可以得到如下动态规划函数:
①V(i, 0)= V(0, j)=0 (把前面i个物品装入容量为0的背包和把0个物品装入容量为j的背包,得到的价值均为0 )②
有5个物品,其重量分别是{2, 2, 6, 5, 4},价值分别为{6, 3, 5, 4, 6},背包的容量为10。问如何挑选物品放入背包,使得背包中的价值最大?
根据动态规划函数,用一个(n+1)×(C+1)的二维表V,V[i][j]表示把前i个物品装入容量为j的背包中获得的最大价值。
初始化0行、0列,然后一行一行计算分析可得出上表。
- import java.util.Scanner;
- public class Main {
- public static void main(String[] args) {
- Scanner cin = new Scanner(System.in);
-
- int n = cin.nextInt(); //物品数
- int m = cin.nextInt(); //背包容量
-
- int[] v = new int[n+5]; //物品价值
- int[] w = new int[n+5]; //物品重量
- int[][] f = new int[n+5][m+5]; //前i个物品装入容量为j的背包中的最大价值
- for(int i=1; i<=n; i++) w[i] = cin.nextInt();
- for(int i=1; i<=n; i++) v[i] = cin.nextInt();
-
- //初始化
- for(int i=0; i<=n; i++) f[i][0] = 0;
- for(int i=0; i<=m; i++) f[0][i] = 0;
-
- for(int i=1; i<=n; i++) {
- for(int j=1; j<=m; j++) {
- if(w[i] > j) f[i][j] = f[i-1][j];
- else f[i][j] = Math.max(f[i-1][j], f[i-1][j-w[i]] + v[i]);
- }
- }
-
- boolean[] x = new boolean[n+5]; //标记物品i是否加入背包
- for(int i=n,j=m; i>=1; i--) {
- if(f[i][j] > f[i-1][j]) {
- x[i] = true;
- j -= w[i];
- }else {
- x[i] = false;
- }
- }
-
- System.out.println("最大价值为:" + f[n][m]); //最大价值
- System.out.print("需要放入背包的物品编号:");
- for(int i=1; i<=n; i++) {
- if(x[i] == true)
- System.out.print(i+" ");
- }
-
- cin.close();
- }
- }
- /**
- 5 10
- 2 2 6 5 4
- 6 3 5 4 6
- */
运行截图
如有错误或不合理的地方,敬请指正~
加油!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。