题目1: 完全背包理论题目
完全背包的题目与01背包相比 就是每个物品可以取用多次。
在背包容量限制下,装满最大价值的物品。
func bagValue(_ weight: [Int], _ value: [Int], _ bagSize: Int) -> Int {
guard weight.count > 0, bagSize > 0 else { return 0 }
var dp = Array(repeating: 0, count: bagSize + 1)
dp[0] = 0
for i in 0..<weight.count {
if bagSize < weight[i] { continue }
// 重点在这里, 背包从小往大遍历,可以做到物品可以重复使用。
for j in weight[i]...bagSize {
dp[j] = max(dp[j], dp[j - weight[i]] + value[i])
}
}
return dp[bagSize]
}
// let val = bagValue([2, 2, 3, 1, 5, 2], [2, 3, 1, 5, 4, 3], 1)
// let val = bagValue([1, 3, 4], [15, 20, 30], 4) // 60
let val = bagValue([1, 2, 3, 4], [2, 4, 4, 5], 5) // 10
print("\(val)")
题目2:518.零钱兑换II
没有AC,应该有值过大 越界问题。 暂未修复。
class Solution {
func change(_ amount: Int, _ coins: [Int]) -> Int {
var dp = Array(repeating: 0, count: amount + 1)
dp[0] = 1
for i in 0..<coins.count {
if amount < coins[i] { continue }
// 顺序遍历 重复取用,完全背包
for j in coins[i]...amount {
// 求组合 的递推公式
dp[j] += dp[j - coins[i]]
}
}
return dp[amount]
}
}
题目3:377. 组合总和 Ⅳ
手动计算了一下,结果如下图(下面描述 以图标注来讲)。
以2行4列的6 举例:
他的结果来自于两部分:
- 不放置物品2的结果, 即1行4列的4。
- 放置物品2的结果, 即3行2列的2。
解释一下为什么放置物品2的时候, 找的是3行2列的结果?
先解释2列: 背包容量4 - 物品2的重量2 = 2,即去找背包容量为2的结果
再解释3行:
3行即是 因为求排列我们会外层遍历背包,内层遍历物品。
遍历是一列一列的进行,那么进行下一列的时候, 滚动数组dp[j]的结果 就已经被刷新到最后一行, 即第三行了。
所以每个数如果求解放置物品case的时候,如果物品有重量,切换行了,那么都是找的最后一行。
当不放置物品的时候,因为还是在取当前列,dp[j]的结果还是上一行的,并不需要找最后一行。
通过以上的描述:反过来理解下外层遍历背包,内层遍历物品为什么就是求的就是排列数?
最后一行的前置结果,意味着用小容量的背包,装过每一个数字了。
当背包+1 再遍历数字的时候, 就会出现 [1, 3] [3, 1]的不同结果了。
// @lc code=start
class Solution {
func combinationSum4(_ nums: [Int], _ target: Int) -> Int {
var dp = Array(repeating: 0, count: target + 1)
dp[0] = 1
// 先遍历背包,求排列数目
// 顺序遍历,可以重复取用
for j in 0...target {
print("\n第\(j)列:")
for (i, num) in nums.enumerated() {
if j >= num {
dp[j] += dp[j - num]
}
print("第\(i)行: \(dp[j])")
}
}
return dp[target]
}
}
// @lc code=end
题目4:爬楼梯进阶版
与组合总和题目一样
属于完全背包种求 排列数量的类型。
func climbingStairs(_ n: Int, _ n: Int) -> Int {
// 1...m 种爬法, n级台阶
var dp = Array(repeating: 0, count: n + 1)
dp[0] = 1
// 先遍历背包 - 求排列
// 顺序遍历 - 每种爬法可以重复进行
for j in 1...n {
// 1...m种爬法
for i in 1...m {
if j >= i {
dp[j] += dp[j - i]
}
}
}
return dp[n]
}