Post

Leetcode Day 32 - DP: Complete Knapsack Problem

Kama 52 Complete Knapsack | 518 Coin Change II | 377 Combination Sum IV | Kama 57 Climbing Stairs

Dynamic Programming

Link to note about Dynamic Programming

Complete Knapsack

Link to the question1

题目描述

小明是一位科学家,他需要参加一场重要的国际科学大会,以展示自己的最新研究成果。他需要带一些研究材料,但是他的行李箱空间有限。这些研究材料包括实验设备、文献资料和实验样本等等,它们各自占据不同的重量,并且具有不同的价值。
小明的行李箱所能承担的总重量为 N,问小明应该如何抉择,才能携带最大价值的研究材料,每种研究材料可以选择无数次,并且可以重复选择。

输入描述

第一行包含两个整数,NV,分别表示研究材料的种类和行李空间
接下来包含 N 行,每行两个整数 wivi,代表第 i 种研究材料的重量和价值

输出描述

输出一个整数,表示最大价值。

输入示例

4 5
1 2
2 4
3 4
4 5

输出示例

10

Solution

A detailed explaination of solution can be found here2.

Python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
N, V = map(int, input().split())

weights = []
values = []

for _ in range(N):
    wi, vi = map(int, input().split())
    weights.append(wi)
    values.append(vi)


dp = [0] * weights[0] + [values[0]] * (V - weights[0] + 1)

for i in range(N):
    for n in range(weights[i], V + 1):
        dp[n] = max(dp[n], dp[n - weights[i]] + values[i])

print(dp[-1])

Coin Change II

Link to Leetcode question3

You are given an integer array coins representing coins of different denominations and an integer amount representing a total amount of money.

Return the number of combinations that make up that amount. If that amount of money cannot be made up by any combination of the coins, return 0.

You may assume that you have an infinite number of each kind of coin.

The answer is guaranteed to fit into a signed 32-bit integer.

Example 1

1
2
3
4
5
6
7
Input: amount = 5, coins = [1,2,5]
Output: 4
Explanation: there are four ways to make up the amount:
5=5
5=2+2+1
5=2+1+1+1
5=1+1+1+1+1

Example 2

1
2
3
Input: amount = 3, coins = [2]
Output: 0
Explanation: the amount of 3 cannot be made up just with coins of 2.

Example 3

1
2
Input: amount = 10, coins = [10]
Output: 1

Solution

A detailed explaination of solution can be found here4.

Python

1
2
3
4
5
6
7
8
9
class Solution(object):
    def change(self, amount, coins):
        dp = [0 for _ in range (amount + 1)]
        dp[0] = 1
        
        for coin in coins:   
            for m in range(coin, amount + 1):
                if m >= coin: dp[m] += dp[m - coin]
        return dp[amount]

Similar Questions

Combination Sum IV

Link to Leetcode question7

Given an array of distinct integers nums and a target integer target, return the number of possible combinations that add up to target.

The test cases are generated so that the answer can fit in a 32-bit integer.

Example 1

1
2
3
4
5
6
7
8
9
10
11
12
Input: nums = [1,2,3], target = 4
Output: 7
Explanation:
The possible combination ways are:
(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1)
Note that different sequences are counted as different combinations.

Example 2

1
2
Input: nums = [9], target = 3
Output: 0

Solution

A detailed explaination of solution can be found here8.

Python

1
2
3
4
5
6
7
8
9
10
class Solution(object):
    def combinationSum4(self, nums, target):
        dp = [0 for _ in range(target + 1)]
        dp[0] = 1

        for t in range(target + 1):
            for num in nums:
                if t >= num: dp[t] += dp[t - num]
        
        return dp[target]

Climbing Stairs

Link to the question9

题目描述

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬至多m (1 <= m < n)个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。

输入描述

输入共一行,包含两个正整数,分别表示n, m

输出描述

输出一个整数,表示爬到楼顶的方法数。

输入示例

3 2

输出示例

3

Solution

A detailed explaination of solution can be found here10.

Python

1
2
3
4
5
6
7
8
9
10
stairs, steps = map(int, input().split())

dp = [0 for _ in range(1 + stairs)]
dp[0] = 1 

for stair in range(stairs + 1):
    for step in range(1, steps + 1):
        dp[stair] += dp[stair - step]

print(dp[stairs])

Reference

This post is licensed under CC BY 4.0 by the author.