递归解法:
public class Main0 {
static int n = 5;
static int[] v={0,3,7,4,49,2};
static int[] w={0,3,4,7,50,2};
public static void main(String[] args){
int AV = 10;
int BV = 50;
System.out.println(get(1,AV,BV));
}
public static int get(int i,int AV, int BV){
if(i==n)if(AV>=v[n]||BV>=v[n])return w[n];
else return 0;
int res = 0;
if(v[i]<=AV) res = Math.max(get(i+1,AV-v[i],BV)+w[i],res);
if(v[i]<=BV) res = Math.max(get(i+1,0,BV-v[i])+w[i],res);
res = Math.max(get(i+1,AV,BV),res);
return res;
}
}
二维数组解法:
public class Main{
static int n = 5;
static int[] v = {0,3,7,4,49,2};
static int[] w = {0,3,4,7,50,2};
public static void main(String[] args){
int AV = 10;int BV = 50;
int[][] fA = new int[n+1][AV+1];
int[][] fB = new int[n+1][BV+1];
for(int i = 1;i<=n;i++)
for (int j = 0; j <= AV; j++) {
fA[i][j] = fA[i - 1][j];
if (j >= v[i])
fA[i][j] = Math.max(fA[i][j], fA[i - 1][j - v[i]] + w[i]);
}
for(int i = 1;i<=n;i++)
for(int j =0;j<=BV;j++){
fB[i][j] = Math.max(fB[i-1][j],fA[i-1][AV]);
if(v[i]<=j){
fB[i][j] = Math.max(fA[i-1][AV]+w[i],fB[i][j]);//启用b
fB[i][j] = Math.max(fB[i-1][j-v[i]]+w[i],fB[i][j]);
}
}
System.out.println(fB[n][BV]);
}
}
压缩至一维(背包1从1-n装,背包2从n-1装)最后返回前i个用背包1装从i+1开始用背包2装的最大值
public class Main1 {
static int n = 5;
static int[] v = {0, 3, 7, 4, 49, 2};
static int[] w = {0, 3, 4, 7, 50, 2};
public static void main(String[] args) {
int AV = 10;int BV = 50;
int[] fA = new int[AV+1];
int[] resA = new int[n + 1];
for (int i = 1; i <= n; i++) {
for (int j = AV; j >= v[i]; j--)
fA[j] = Math.max(fA[j], fA[j - v[i]] + w[i]);
resA[i] = fA[AV];//装至第i个物品价值的最大值为
}
int[] fB = new int[BV+1];int[] resB = new int[n+1];
for(int i = n;i>0;i--){
for(int j = BV;j>=v[i];j--)
fB[j] = Math.max(fB[j],fB[j-v[i]]+w[i]);
resB[i] = fB[BV];//小心越界(0,n,n-1....1)
}
int res = 0;
// System.out.println(Arrays.toString(resA));System.out.println(Arrays.toString(resB));
for(int i = 0;i<=n;i++)
res = Math.max(resA[i]+resB[i],res);
System.out.println(res);
}
}