01背包是在M件物品取出若干件放在空间为W的背包里,每件物品的体积为C1,C2,…,Cn,与之相对应的价值为W1,W2,…,Wn.求解将那些物品装入背包可使总价值最大。
动态规划(DP):
1) 子问题定义:F[i][j]表示前i件物品中选取若干件物品放入剩余空间为j的背包中所能得到的最大价值。
2) 根据第i件物品放或不放进行决策
{ F[i-1][j] , j<weight[i] 第i件物品的重量大于当前背包的容量
F[i][j]= Max|
{ max{F[i-1][j-weight[i]]+value[i],F[i-1][j]} j>=weight[i],可以放入第i件商品 (1-1)
其中F[i-1][j]表示前i-1件物品中选取若干件物品放入剩余空间为j的背包中所能得到的最大价值;
而F[i-1][j-C[i]]+W[i]表示前i-1件物品中选取若干件物品放入剩余空间为j-C[i]的背包中所能取得的最大价值加上第i件物品的价值。
根据第i件物品放或是不放确定遍历到第i件物品时的状态F[i][j]。
设物品件数为n,背包容量为m,第i件物品重量为weight[i],第i件物品价值为value[i]。
import java.util.Scanner;
/**
* Created by sunwl1993 on 2017/11/6.
*/
public class 零一背包问题 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();//物品个数
int m = sc.nextInt();//最大容量
int[] weight = new int[n];//每个物品的重量
int[] value = new int[n];//每个物品的价值
for (int i = 0; i < n; i++)
weight[i] = sc.nextInt();
for (int i = 0; i < n; i++)
value[i] = sc.nextInt();
int maxValue[][] = new int[n + 1][m + 1];//maxValue[i][j]表示当前背包容量为j时,前i个物品的最大价值
maxValue(maxValue, weight, value, n, m);
}
public static void maxValue(int[][] maxValue, int[] weight, int[] values, int n, int m) {
int [][]temp = new int[n+1][m+1];
for (int i = 0; i <= n; i++)
maxValue[i][0] = 0;
for (int i = 0; i <= m; i++)
maxValue[0][i] = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
if (weight[i - 1] > j)
maxValue[i][j] = maxValue[i - 1][j];
else {
if (maxValue[i - 1][j - weight[i - 1]] + values[i - 1] > maxValue[i - 1][j])
{
maxValue[i][j] = maxValue[i - 1][j - weight[i - 1]] + values[i - 1];
temp[i][j]=1;
}
else
maxValue[i][j] = maxValue[i - 1][j];
}
}
System.out.println(maxValue[n][m]);
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= m; j++)
System.out.print(maxValue[i][j] + " ");
System.out.println();
}
while(m>0&&n>0){
if(temp[n][m]==1)
{
System.out.print(values[n-1]+" ");
m = m -weight[n-1];
}
n--;
}
}
}