动态规划入门-01背包问题
问题描述
假设你有个最大载重量为 300 k g 300kg 300kg的背包,有4个物品。它们的重量分别为 123 k g , 88 k g , 93 k g , 100 k g 123kg,88kg,93kg,100kg 123kg,88kg,93kg,100kg,价值分别为$$10,$19,$8,$20$。
请问背包内最大可以放入多少价值的物品?
问题求解
这个问题被称为01背包问题,是典型的动态规划例题。
这里的价值是我们要优化的目标值,物品数目和重量为两个状态,所以依据这两个状态可以定义二维dp数组。
对于每个物品,我们有两种选择,即放入背包或者不放入背包。
我们设数组f[n][w]
代表前n个物品在w容量的背包里可以放入的最大价值。
当没有物品或者背包容量为0时,价值显然是0:
f
[
0
]
[
w
]
=
f
[
n
]
[
0
]
=
0
f[0][w] = f[n][0] = 0
f[0][w]=f[n][0]=0
我们求解的是背包内的物品价值最大化,则状态转移为:
f
[
i
]
[
j
]
=
{
f
[
i
−
1
]
[
j
]
,
w
[
i
]
>
j
m
a
x
(
f
[
i
−
1
]
[
j
]
,
f
[
i
−
1
]
[
j
−
w
[
i
]
]
+
v
[
i
]
)
,
w
[
i
]
≤
j
f[i][j] = \begin{cases} f[i-1][j] &, w[i]>j \\ max(f[i-1][j],f[i-1][j-w[i]] + v[i]) &, w[i] \leq j \end{cases}
f[i][j]={f[i−1][j]max(f[i−1][j],f[i−1][j−w[i]]+v[i]),w[i]>j,w[i]≤j
代码实现
Java
public class mian {
static int maxVal(int[] w,int[] v,int maxw) {
int n = w.length;
int[][] f = new int[n][maxw+1];
for (int i = 1; i < n; i++) {
for (int j = 1; j <= maxw; j++) {
if (j < w[i]) {
f[i][j] = f[i-1][j];
} else {
f[i][j] = Math.max(f[i-1][j-w[i]] + v[i],f[i-1][j]);
}
}
}
return f[n-1][maxw];
}
public static void main(String[] args) {
int[] w = {123, 88, 93, 100};
int[] v = {10, 19, 8, 20};
int maxw = 300;
System.out.println(maxVal(w,v,maxw)); // 47
}
}