问题描述:
使用穷举法解决0/1背包问题。问题描述:给定n个重量为{w1, w2, … ,wn}、价值为{v1, v2, … ,vn}
的物品和一个容量为C的背包,求这些物品中的一个最有价值的子集,且要能够装到背包中。
穷举法:每件物品装还是不装有两种选择,使用0-表示不装,1表示装,n件物品就有2^n种,穷举2^n种,找到符合符合weight背包容量的且为价值最大的方式。
public class Main01 {
//穷举法
public void pack01(int weight,int[] wt,int[] val){
int n = wt.length;
int count= (int) Math.pow(2,n);
int maxVal = 0;
//枚举32种情况,并且记录符合weight重量背包的最大价值
for (int i = 0; i < count; i++) {
String res = String.format("%5s",Integer.toBinaryString(i)).replace(' ','0');
System.out.print(res+" ");
int sumVal = 0;
int sumWeight=0;
for (int j = 0; j < n; j++) {
//为1时表示装该物品 0表示不准装
if (res.charAt(j)=='1') {
sumVal += val[j];
sumWeight += wt[j];
}
if (sumWeight<=weight){
maxVal = Math.max(sumVal,maxVal);
}
}
System.out.println("价值:"+sumVal+"重量:"+sumWeight);
}
//打印最大价值下对应的背包实际重量和所装物品的状态
for (int i = 0; i<count; i++) {
String res = String.format("%5s",Integer.toBinaryString(i)).replace(' ','0');
int sumVal = 0;
int sumWeight=0;
for (int j = 0; j < n; j++) {
if (res.charAt(j)=='1') {
sumVal += val[j];
sumWeight += wt[j];
}
}
if (sumVal==maxVal&&sumWeight<=weight){
System.out.println("当背包重量为"+weight+"时:最大价值:"+sumVal+" 总重量: "+sumWeight+" 方式:"+res);
break;
}
}
}
public static void main(String[] args) {
Main01 main01 = new Main01();
int[] wt = {1, 2, 1, 12, 4};
int[] val = {1, 2, 2, 4, 10};
main01.pack01(15, wt, val);
}
}
输出结果:
二维dp数组:
dp[i][w]数组含义:对于前i个物品,当前背包容量为w时,可装下的最大值是dp[i][w]。
dp[i-1][w-wt[i-1]]+val[i-1]:装物品i的价值
dp[i-1][w]:不装物品i的价值
因此dp[i][w]取装物品 i dp[i-1][w-wt[i-1]]+val[i-1] 和 不装物品i dp[i-1][w] 的最大值
public class Main01 {
public static void main(String[] args) {
int[] wt = {1, 2, 1, 12, 4};
int[] val = {1, 2, 2, 4, 10};
int res = pack01(15,wt,val);
System.out.println("最大价值:"+res);
}
public static int pack01(int weight,int[] wt,int[] val){
int n = wt.length;
//dp[i][w]数组含义:对于前i个物品,当前背包容量为w时,可装下的最大值是dp[i][w]
int[][] dp = new int[n+1][weight+1];
for (int i = 1; i <= n; i++) {
for (int w = 1; w <= weight; w++) {
if (wt[i-1]>w){
//不能装入背包
dp[i][w] = dp[i-1][w];
}else {//择优装入背包
dp[i][w] = Math.max(dp[i-1][w-wt[i-1]]+val[i-1],dp[i-1][w]);
}
}
}
//打印dp表
for (int i = 0; i <=n ; i++) {
for (int j = 0; j <=weight ; j++) {
if (j<weight){
System.out.print(dp[i][j]+",");
}else {
System.out.print(dp[i][j]);
}
}
System.out.println();
}
return dp[n][weight];
}
}
输出结果: