0-1背包问题:
一个可装载重量为 W
的背包和 N
个物品,每个物品有重量和价值两个属性。其中第 i
个物品的重量为 wt[i]
,价值为 val[i]
,现在让你用这个背包装物品,最多能装的价值是多少?
0-1是因为物体默认不可分割,只有装进去,不装进去。
动态规划需要明确的就是状态和选择,
状态就是情景的形容,对于背包问题,需要明确的就是背包的承重和可选择的物品;
选择就是是否将当前物品放入,即放入、不放入两种选择。
之后我们需要定义一个二位数组,用于记录当前的背包状态,
dp[i][j]:其中i代表了可选择的i个物品,能装下的的总量为j,dp代表当前状态下的最大容纳价值,比如说,如果 dp[3][5] = 6
,其含义为:对于给定的一系列物品中,若只对前 3 个物品进行选择,当背包容量为 5 时,最多可以装下的价值为 6。
状态转移:
如果你没有把这第 i
个物品装入背包,那么很显然,最大价值 dp[i][w]
应该等于 dp[i-1][w]
,继承之前的结果。
如果你把这第 i
个物品装入了背包,那么 dp[i][w]
应该等于 dp[i-1][w - wt[i-1]] + val[i-1]
。你如果装了第 i
个物品,就要寻求剩余重量 w - wt[i-1]
限制下的最大价值,加上第 i
个物品的价值 val[i-1]
。
通俗来讲,就是做了一个二位数组,用来记录每个物品放入或者不放入的最大价值,行代表放入物品,列代表背包容量
dp = [[
0
]*(n+
1
)
for
_ in range(m+
1
)]
for
i in range(
1
,m+
1
):
for
j in range(
1
,n+
1
):
if
j-w[i]>=
0
:
dp[i][j] = max(dp[i-
1
][j], dp[i-
1
][j-w[i]]+v[i])
else
:
dp[i][j] = dp[i-
1
][j]
return
dp[m][n]