1、0-1背包问题
物品 | 重量 | 价格 |
吉他 | 1 | 1500 |
音响 | 4 | 3000 |
电脑 | 3 | 2000 |
背包的填表过程:
物品\重量 | 0磅 | 1磅 | 2磅 | 3磅 | 4磅 |
0 | 0 | 0 | 0 | 0 | |
吉他 | 0 | 1500 | 1500 | 1500 | 1500 |
音响 | 0 | 1500 | 1500 | 1500 | 3000 |
电脑 | 0 | 1500 | 1500 | 2000 | 2000+1500=3500 |
代码实现如下(两种方式:一纬数组和二维数组)
public class Main {
public static void main(String[] args) {
int totalweight = 4;
int values[] = {1500, 3000, 2000};
int weights[] = {1, 4, 3};
System.out.println(bag(totalweight,weights,values));
System.out.println(bag01(totalweight, weights, values));
}
//二维数组实现背包问题
public static int bag(int totalV, int[] weights, int[] values) {
if (weights == null || weights.length == 0) {
return 0;
}
int n = weights.length;
int m = totalV;
//创建二维数组,v[i][j]表示在前i个物品中能够装入容量为j的背包中的最大价值
int[][] v = new int[n + 1][m + 1];
//初始化第一行和第一列,这里本程序可以不用处理,因为默认就是0
for (int i = 0; i < v.length; i++) {
v[i][0] = 0;//将第一列设置为0
}
for (int j = 0; j < v[0].length; j++) {
v[0][j] = 0; //第一行设置为0
}
for (int i = 1; i < v.length; i++) {
for (int j = 1; j < v[0].length; j++) {
if (weights[i-1] > j) {//weights[i-1]表示第一件物品的重量
v[i][j] = v[i - 1][j];
} else {
v[i][j]=Math.max(v[i-1][j],v[i-1][j-weights[i-1]]+values[i-1]);
}
}
}
return v[n][m];
}
//非递归一纬数组 totalV是背包的容量
public static int bag01(int totalV, int[] weights, int[] values) {
if (weights == null || weights.length == 0) {
return 0;
}
int goodsNum = weights.length;
int f[] = new int[totalV + 1];
for (int i = 0; i < goodsNum; i++) {
int w = weights[i];
int v = values[i];
for (int j = totalV; j >= w; j--) {
f[j] = Math.max(f[j], f[j - w] + v);
//f[j]表示:前i个物品放入容量为j的背包的最大价值
}
}
return f[totalV];
}
}
2、完全背包以及变种问题,请参考如下链接
经典算法总结——背包问题(java实现)【已完结】_包里面装东西 算法_lanyu_01的博客-CSDN博客
人民币组合问题:算法笔试题:1元,5元,10元,20元,50元、100元面值人民币组合给定x元的问题_LarsCheng的博客-CSDN博客
最长公共子序列: