经典的动态规划问题。
本篇也许是最通俗易懂的0-1背包问题解答。
问题描述:一个背包有一定的承重cap,有n件物品,每件都有自己的价值,记录在数组v中,也都有自己的重量,记录在数组w中,每件物品只能选择要装入背包还是不装入背包,要求在不超过背包承重的前提下,选出物品的总价值最大。
这道题如果是给你一个包,一堆物品,相信要不了一分钟你就能装好这个包。但是怎么让计算机算出来呢?其实计算机计算时远没有我们聪明,它只能一个一个去试,基本上罗列出所有的办法,最终得到最优解。而动态规划本质上没有减轻计算机大量计算的负担,只是让它计算的有规律,尽可能的减少重复计算,并且以牺牲空间为代价,换取时间上的效率。
动态规划问题连载了5篇文章了,并且找零钱问题通过使用了三种办法循序渐进得到动态规划的解答。相信对于动态规划肯定有了一些认识和理解。
简单的总结,动态规划肯定需要个矩阵,也就是二维数组。算出第一行第一列,就可以循环求出整个矩阵来。本题也不例外。
新建二维数组dp[i][j],dp[i][j]表示使用前i件物品,在不超过j重量的情况下达到的最大价值。为什么要这样想?
换个角度,先来求出dp[i][j],然后就知道原因了。dp[i][j]的值有两种情况。
一种是等于dp[i-1][j],这种情况的描述是,不拿第i件物品,前i-1件物品在不超过j重量的情况下的最大价值。换个说法,包没有可用重量让我拿第i件物品了,所以dp[i][j]=dp[i-1][j]。
另一种情况dp[i][j]等于dp[i-1][j-w[i]]+v[i]。看起来有一些复杂,它的情况描述是,拿上第i件物品,其价值是前i-1件物品在不超过j-w[i]重量情况下的最大价值加上第i件物品本身的价值。换个说法,现在要拿上第i件物品,就需要包至少有i这件物品的可用重量。
这就是背包问题求dp[i][j]的两种情况,具体是哪一种?哪个大是哪个。给一个具体的例子。
物品有5件。包的承重cap是20。物品价值数组v是{3,5,2,1,4},重量数组是{2,1,3,4,6}。那么新建数组dp[5][20+1],因为最终求的是dp[5][20],所以重量要多建一个单位。矩阵如下:
0 | 1 | 2< |
---|