import java.util.Arrays; import java.util.Scanner; public class Main { public static void main(String[] args) { // TODO Auto-generated method stub Scanner scanner=new Scanner(System.in); int n=scanner.nextInt(); int V=scanner.nextInt(); int v[]=new int[n]; int w[]=new int[n]; for (int i = 0; i < w.length; i++) { v[i]=scanner.nextInt();//体积 w[i]=scanner.nextInt();//价值 } /* * int dp[][]=new int[n][V+1];//dp[i][j]表示在体积为j的情况下,考虑是否装第i件物品,使得价值最大 //初始化 for * (int i = 0; i < dp.length; i++) { dp[i][0]=0; } for (int j = 0; j < V+1; j++) * { if(j>=v[0])dp[0][j]=w[0]; } for (int i = 1; i < n; i++) { for (int j = 1; j * < V+1; j++) { if(j>=v[i]) { dp[i][j]=Math.max(dp[i-1][j-v[i]]+w[i], * dp[i-1][j]); }else { dp[i][j]=dp[i-1][j]; } * * } } System.out.println(dp[n-1][V]); */ //不要求全部装满 int dp1[]=new int[V+1]; for (int i = 0; i < n ; i++) { for (int j = V; j >= v[i]; j--) { dp1[j]=Math.max(dp1[j], dp1[j-v[i]]+w[i]); } } System.out.println(dp1[V]); //下面计算要求背包恰好装满的最大价值 long dp2[]=new long[V+1]; Arrays.fill(dp2, -1);//负数表示无法恰好装满 dp2[0]=0;//初始化,容量为0肯定能装满 for (int i = 0; i < n; i++) { for (int j = V; j >= v[i]; j--) { if(dp2[j-v[i]]!=-1) { dp2[j]=Math.max(dp2[j-v[i]]+w[i], dp2[j]); } } } if(dp2[V]!=-1) { System.out.println(dp2[V]); }else { System.out.println(0); } } }
01背包我之前只会二维dp版的,没想到还有一维dp优化版,首先讲一下不要求恰好装满的情况,我们创建一维dp1数组,dp1[j]表示在容量为j的情况下,能装的最大价值。dp1[j]=Math.max(dp1[j], dp1[j-v[i]]+w[i]);循环中j要求逆序,也就是i从V+1到v[i],这样才能保证后面的结果不会把前面的结果覆盖。
要求恰好装满的情况,我们先把dp2的所有元素赋为-1,然后把dp[0]赋值为0,因为当容量为0时,一定能恰好装满,且价值为0。后买如果dp2[j-v[i]]不等于-1,也就是那个容量下就已经能装满了,我现在恰好给它增加v[i]的容量,那肯定也可以装满v[i]