问题描述:
有n个重量和价值分别为wi,vi的物品,从这些物品中挑选出总重量不超过m的物品,求所有挑选方案中价值总和的最大值。
思路分析:
问题可以看做往一个载重量为m的背包中装入有限数量的物品,求装入物品的最大价值。这里物品的件数都为1,所以每个物
品都只有两种选择,要么放入背包,要么不放。在背包容量为j时,对前i件物品来说,设它的最大价值为dp[i][j],它
的最大价值状态转移公式为:
当第i件物品比背包容量还大时,dp[i][j]等于前i-1件物品放入这个背包的最大价值。
dp[i][j]=dp[i-1][j] (j<w[i])
当第i件物品能放入背包时,分为两种情况,选择放和不放,不放的话和上面公式相同,放的话则背包容量减去第i件
物品的重量再去装前i-1件物品,所得的最大价值加上第i件物品的价值。两种情况中较大的那种即为最优解。
dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]) (j>=w[i])
问题可以看做往一个载重量为m的背包中装入有限数量的物品,求装入物品的最大价值。这里物品的件数都为1,所以每个物
品都只有两种选择,要么放入背包,要么不放。在背包容量为j时,对前i件物品来说,设它的最大价值为dp[i][j],它
的最大价值状态转移公式为:
当第i件物品比背包容量还大时,dp[i][j]等于前i-1件物品放入这个背包的最大价值。
dp[i][j]=dp[i-1][j] (j<w[i])
当第i件物品能放入背包时,分为两种情况,选择放和不放,不放的话和上面公式相同,放的话则背包容量减去第i件
物品的重量再去装前i-1件物品,所得的最大价值加上第i件物品的价值。两种情况中较大的那种即为最优解。
dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]) (j>=w[i])
以上是一位大神的二维的01背包解决方案,后来有学习到了如何用一维数组去实现这种问题
以下是一维数组的解决方案
import java.util.Scanner;
public class 背包01 {
static int w[] =new int [105];
static int v[] = new int[105];
static int [] dp = new int[10000];
static int n,we;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
we = sc.nextInt();
for(int i=1;i<=n;i++){
w[i]=sc.nextInt();
}
for(int i=1;i<=n;i++){
v[i]=sc.nextInt();
}
dp();
System.out.println(dp[we]);
}
private static void dp() {//物品数量为j 容量为i 背包容量为i的时候dp[i]存当前最大价值
for(int i=1;i<=we;i++){
int max=0;
for(int j=1;j<=n;j++){
//这里的意思是,背包的容量从1-->we的过程中,逐个去扫描每个物品的重量,如果比当前的背包容量小,那就来判断一下最优方案
//dp[i-w[j]]是曾经容量为i-w[j]的时候背包最优的解决方案,和i-1容量的时候进行价值最大化比较
//从而实现背包空间增长时候的即时更新最大价值,为下一个状态做好基础,便于状态转移
dp[i]=w[j]<=i?max(dp[i-w[j]]+v[j],dp[i-1],max):dp[i-1];
max=dp[i];
//之前这个地方没有max的时候,dp[i]被覆盖了n次,导致了结果不正确
System.out.println(i+": "+dp[i]);
}
}
}
private static int max(int i, int j,int k) {
int max=0;
if(i>j)max=i;else max=j;
return k>max?k:max;
}
}
我使用的测试用例以及结果
3
40
25 20 15
25 20 15
结果:
1: 0
1: 0
1: 0
2: 0
2: 0
2: 0
3: 0
3: 0
3: 0
4: 0
4: 0
4: 0
5: 0
5: 0
5: 0
6: 0
6: 0
6: 0
7: 0
7: 0
7: 0
8: 0
8: 0
8: 0
9: 0
9: 0
9: 0
10: 0
10: 0
10: 0
11: 0
11: 0
11: 0
12: 0
12: 0
12: 0
13: 0
13: 0
13: 0
14: 0
14: 0
14: 0
15: 0
15: 0
15: 15
16: 15
16: 15
16: 15
17: 15
17: 15
17: 15
18: 15
18: 15
18: 15
19: 15
19: 15
19: 15
20: 15
20: 20
20: 20
21: 20
21: 20
21: 20
22: 20
22: 20
22: 20
23: 20
23: 20
23: 20
24: 20
24: 20
24: 20
25: 25
25: 25
25: 25
26: 25
26: 25
26: 25
27: 25
27: 25
27: 25
28: 25
28: 25
28: 25
29: 25
29: 25
29: 25
30: 25
30: 25
30: 30
31: 30
31: 30
31: 30
32: 30
32: 30
32: 30
33: 30
33: 30
33: 30
34: 30
34: 30
34: 30
35: 30
35: 35
35: 35
36: 35
36: 35
36: 35
37: 35
37: 35
37: 35
38: 35
38: 35
38: 35
39: 35
39: 35
39: 35
40: 40
40: 40
40: 40
40
状态即时更新,不会存在dp[i]被覆盖的情况,保证在背包容量在逐渐增大的时候,每时每刻都是最优的解决方案