递归解法:
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); } }