当前位置:网站首页>Leetcode: 0-1 knapsack problem in dynamic programming [come and set the template directly]
Leetcode: 0-1 knapsack problem in dynamic programming [come and set the template directly]
2022-07-19 03:21:00 【lucky-wz】
PS. 0-1 Knapsack problem is undoubtedly a very classic class of dynamic programming problems , Here is a template for solving this kind of problem . This article is for reference Random code recording Some notes made , Please stamp the link for the full version .
standard 0-1 knapsack problem
Two dimensional array solution
Standard knapsack problem : Yes n Items and one can carry a maximum weight of w The backpack . The first i The weight of the item is weight[i], The value is value[i]. Each item can only be used once , Solve which items are loaded into the backpack, and the total value of the items is the largest .
Each item actually has only two states , Take it or not , So you can use the backtracking method to search all the cases , So time complexity is o ( 2 n ) o(2^n) o(2n), there n n n The number of items . So the solution to violence is exponential time complexity , So we need the solution of dynamic programming to optimize !
for instance : The maximum weight of the backpack is 4. Item is :
| weight | value | |
|---|---|---|
| goods 0 | 1 | 15 |
| goods 1 | 3 | 20 |
| goods 2 | 4 | 30 |
What's the maximum value of the items a backpack can carry ?
dp[i][j] Indicates from subscript [0-i] Take whatever you want from your belongings , Put in capacity j The sum of the maximum value of the backpack .
The recursive formula : There are two directions to push out dp[i][j]:
- No objects
i: fromdp[i - 1][j]Introduction , The capacity of the backpack isj, There are no items in itiMaximum value of , heredp[i][j]Namelydp[i - 1][j].( It's actually when thingsiIt weighs more than a backpackjWhen the weight of , goodsiCan't put it in the backpack , So the value in the backpack is still the same as before .) - Put things
i: fromdp[i - 1][j - weight[i]]Introduction ,dp[i - 1][j - weight[i]]The capacity of the backpack isj - weight[i]Don't put things when you areiMaximum value of , thatdp[i - 1][j - weight[i]] + value[i]( goodsiThe value of ), Is to put things in your backpackiGet the most value .
So the recursive formula : dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]).
initialization :
- from
dp[i][j]Starting from the definition of , If the backpack capacityjby 0 Words , namelydp[i][0], No matter what items you choose , The total value of the backpack must be 0. - As can be seen from the state transition equation
iByi-1derived , thatiby 0 Be sure to initialize .dp[0][j], namely :iby 0, Storage number 0 When you get your stuff , The maximum value that a backpack of each capacity can store . So obviously whenj < weight[0]When ,dp[0][j]Should be 0, Because the backpack has more capacity than the number 0 The weight of the goods is still small . Whenj >= weight[0]when ,dp[0][j]Should bevalue[0], Because the backpack has enough capacity to put numbers 0 goods .
Initialization code :
for i in range(rows):
dp[i][0] = 0
for i in range(1, cols):
if i >= weight[0]:
dp[0][i] = value[0]
This problem has two traversal dimensions : Item and backpack weight . that , First traverse the items or the weight of the backpack ? In fact, it can be !!
Go through the items first , Then traverse the backpack weight :
for i in range(1, len(weight)):
for j in range(1, bag_size + 1):
if weight[i] > j:
dp[i][j] = dp[i - 1][j]
else:
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i])
Go through the backpack first , Then traverse the items :
for i in range(1, bag_size + 1):
for j in range(1, len(weight)):
if weight[j] > i:
dp[j][i] = dp[j - 1][i]
else:
dp[j][i] = max(dp[j - 1][i], dp[j - 1][i - weight[j]] + value[j])
The complete code is as follows :
# The maximum weight of the backpack is 4. Item is :
# weight value
# goods 0 1 15
# goods 1 3 20
# goods 2 4 30
# What's the maximum value of the items a backpack can carry ?
""" Two dimensional array implementation dp[i][j] Indicates from subscript [0-i] Take whatever you want from your belongings , Put in capacity j The backpack , What is the maximum total value . """
def test_2_wei_bag_problem1(bag_size, weight, value):
dp = [[0 for _ in range(bag_size + 1)] for _ in range(len(weight))]
for i in range(len(weight)):
dp[i][0] = 0
for j in range(weight[0], bag_size + 1):
dp[0][j] = value[0]
# Go through the backpack first
for i in range(1, bag_size + 1):
for j in range(1, len(weight)):
if weight[j] > i:
dp[j][i] = dp[j - 1][i]
else:
dp[j][i] = max(dp[j - 1][i], dp[j - 1][i - weight[j]] + value[j])
# Go through the items first
for i in range(1, len(weight)):
for j in range(1, bag_size + 1):
if weight[i] > j:
dp[i][j] = dp[i - 1][j]
else:
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i])
return dp[len(weight) - 1][bag_size]
if __name__ == '__main__':
bag_size = 4
weight = [1, 3, 4]
value = [15, 20, 30]
ret = test_2_wei_bag_problem1(bag_size, weight, value)
print(ret)
One dimensional array solution
For the knapsack problem, the state can be compressed . When using two-dimensional arrays , The recursive formula :dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]); In fact, it can be found that if dp[i - 1] Copy that layer to dp[i] On , The expression can be :dp[i][j] = max(dp[i][j], dp[i][j - weight[i]] + value[i]). Instead of putting dp[i - 1] Copy this layer to dp[i] On , Let's just use one-dimensional array , Only dp[j].
This is it. Scrolling array The origin of , The condition to be met is that the upper layer can be reused , Copy directly to the current layer .
Restate the definition :dp[i][j]** Indicates from subscript **[0-i] Take whatever you want from your belongings , Put in capacity j The backpack , What is the maximum total value .
that , In one dimension dp Array ,dp[j] Express : Capacity of j The backpack , The value of the items carried can be up to dp[j].
dp[j] Can pass dp[j - weight[i]] derived ,dp[j - weight[i]] The capacity is j - weight[i] The maximum value of your backpack .dp[j - weight[i]] + value[i] The capacity is j - goods i weight The backpack Add items i The value of .( That is, the capacity is j The backpack , Put something in i After that, the value is :dp[j])
here dp[j] There are two choices :
- One is to take yourself
dp[j], This is equivalent todp[i-1][j], I.e. no objectsi; - One is to take
dp[j - weight[i]] + value[i], That is to put thingsi.
Specify the maximum , You can get dp[j].
So the recursive formula is :dp[j] = max(dp[j], dp[j - weight[i]] + value[i]).
initialization :
dp[0]It should be 0, Because the backpack has a capacity of 0 The greatest value of the items carried is 0;- The rest is initialized to 0 that will do , Because we can see from the recursive formula , Other
dpWill be covered .
traversal order : A two-dimensional dp When traversing , Backpack capacity is from small to large , and A one-dimensional dp When traversing , Backpacks are from big to small . Why? ? Traversal in reverse order is to ensure that items i Only once !. But if once the positive order traverses , So the object 0 Will be repeated many times !
Let's look at two nested for The order of the cycle , The code must first traverse the items and then nest and traverse the backpack capacity , You can't traverse the backpack capacity and nested items first ! Because one dimension dp Writing , Backpack capacity must be traversed in reverse order , If the traversal backpack capacity is placed on the upper layer , Then each dp[j] Only one item will be put in , namely : There is only one item in the backpack .
One dimensional array code :
# The maximum weight of the backpack is 4. Item is :
# weight value
# goods 0 1 15
# goods 1 3 20
# goods 2 4 30
# What's the maximum value of the items a backpack can carry ?
""" One dimensional array implementation dp[j] Express : Capacity of j The backpack , The value of the items carried can be up to dp[j] """
def wei_bag_problem1(bag_size, weight, value):
dp = [0 for _ in range(bag_size + 1)]
# Go through the items first , And then traverse the backpack
for i in range(len(weight)):
for j in range(bag_size, i, -1):
if j >= weight[i]:
dp[j] = max(dp[j], dp[j - weight[i]] + value[i])
return dp[-1]
if __name__ == '__main__':
bag_size = 4
weight = [1, 3, 4]
value = [15, 20, 30]
ret = wei_bag_problem1(bag_size, weight, value)
print(ret)
Classic title
416. To divide into equal and subsets
To give you one Contains only positive integers Of Non empty Array nums . Please decide whether you can divide this array into two subsets , Make the sum of the elements of the two subsets equal .
First , Clarify the following four points , In fact, this problem is a 01 knapsack problem .
- The volume of the backpack is
sum / 2 - The goods to be put in the backpack ( The elements in the set ) Weight is The value of the element , The value is also the value of the element
- If the backpack is just full , Indicates that the sum of
sum / 2Subset . - Every element in the backpack can't be put repeatedly .
dp[j] Express The total capacity of the backpack is j, The maximum can be made up j The sum of the subsets of is dp[j].
This topic , It's equivalent to putting values in your backpack , So the object i The weight of is nums[i], Its value is also nums[i]. So the recurrence formula :dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]).
from dp[j] By definition , First dp[0] It must be 0. If the value given by the title is a positive integer, then it is not 0 Subscripts are initialized to 0 That's all right. , If the title gives a negative value , So no 0 The subscript is initialized to negative infinity . In this way, we can make dp The maximum value of array in the process of recursive formula , Instead of being overwritten by the initial value .
class Solution:
def canPartition(self, nums: List[int]) -> bool:
'''dp[j] Express The total capacity of the backpack is j, The maximum can be made up j The sum of the subsets of is dp[j]'''
sums = sum(nums)
if sums % 2 == 1: return False
dp = [0] * 10001
target = sums // 2
for i in range(0, len(nums)): # Traverse the items
for j in range(target, nums[i] - 1, -1): # Traverse the backpack
dp[j] = max(dp[j], dp[j - nums[i]] + nums[i])
# The sum of the elements in the set can be made exactly target
if dp[target] == target:
return True
else:
return False
1049. The weight of the last stone II
There is a pile of stones , Use an array of integers stones Express . among stones[i] It means the first one i The weight of a stone . Every round , Choose any two stones , Then smash them together . Suppose the weights of the stones are x and y, And x <= y. The possible results of crushing are as follows :
- If x == y, Then both stones will be completely crushed ;
- If x != y, So the weight is x The stone will be completely crushed , And the weight is y The new weight of the stone is y-x.
Last , There's only one piece left at most stone . Return to this stone The smallest possible weight . If there is no stone left , Just go back to 0.
In fact, this problem is to divide the stones into two piles with the same weight , The smallest stone left after the collision , This is actually 01 knapsack problem .
dp[j] The capacity is j The backpack , You can recite at most dp[j] Such a heavy stone . Others are actually the same as the above question . The code is as follows :
class Solution:
def lastStoneWeightII(self, stones: List[int]) -> int:
total_sum = sum(stones)
target = total_sum // 2
dp = [0] * (target + 1)
for i in range(len(stones)):
for j in range(target, -1, -1):
if j >= stones[i]:
dp[j] = max(dp[j], dp[j - stones[i]] + stones[i])
return total_sum - dp[target] - dp[target]
494. Objectives and
Give you an array of integers nums And an integer target . Add... Before each integer in the array ‘+’ or ‘-’ , And then concatenate all the integers , You can construct a expression :
- for example ,nums = [2, 1] , Can be in 2 Before adding ‘+’ , stay 1 Before adding ‘-’ , And then concatenate them to get the expression “+2-1”
Returns the 、 The result is equal to target Different expression Number of .
Suppose the sum of the additions is x, Then the sum corresponding to subtraction is sum - x. So what we ask is x - (sum - x) = target, solve equations , That is to say x = (S + sum) / 2. At this point, the problem turns into , The full capacity is x knapsack , There are several ways .
First , above x The solution involves division , Then we need to consider whether rounding down has any impact :
(S + sum) % 2 == 1: Obviously , There is no solution to this situation !abs(target) > sum: There is no solution to this situation , After all, the target sum is larger than the sum of the array , How can there be a solution ?
dp[j] Express : fill j( Include j) Such a large volume bag , Yes dp[j] Methods .
Don't consider nums[i] Under the circumstances , The filling capacity is j - nums[i] The backpack , Yes dp[j - nums[i]] Methods . So just get nums[i] Words , manage to put together dp[j] There is dp[j - nums[i]] Methods . Then round it up dp[j] How many methods are there , That is the be-all dp[j - nums[i]] Add up .
Find the formula of combinatorial problems , It's all like this :
dp[j] += dp[j - nums[i]]
As can be seen from the recursive formula , At initialization time dp[0] Be sure to initialize to 1, because dp[0] Is the origin of all recursive results in the formula , If dp[0] yes 0 Words , The recursive result will be 0.dp[0] = 1, It's also easy to explain in theory , The full capacity is 0 The backpack , Yes 1 Methods , It's just pretend 0 Item .
The code implementation is as follows :
class Solution:
def findTargetSumWays(self, nums: List[int], target: int) -> int:
total_sum = sum(nums)
if abs(target) > total_sum: return 0
if (target + total_sum) % 2 == 1: return 0
bagsize = (target + total_sum) // 2
dp = [0] * (bagsize + 1)
dp[0] = 1 # The full capacity is 0 The backpack , Yes 1 Methods , It's just pretend 0 Item
for i in range(len(nums)):
for j in range(bagsize, nums[i] - 1, -1):
dp[j] += dp[j - nums[i]]
return dp[bagsize]
474. One and zero (🧡🧡)
Here's an array of binary strings strs And two integers m and n . Please find out and return to strs Length of the largest subset of , This subset most Yes m individual 0 and n individual 1 . If x All of the elements of are also y The elements of , aggregate x Is a collection y Of A subset of .
it is to be noted that , This question is not about multiple backpacks , In this question strs The elements in the array are items , Every item is a ! and m and n It's like a backpack , Two dimensional backpack . Carefully understand here !
dp[i][j]: At most i individual 0 and j individual 1 Of strs The size of the largest subset of is dp[i][j].
dp[i][j] It can be from the previous strs Derived from the string in ,strs The string in the has zeroNum individual 0,oneNum individual 1.dp[i][j] It could be dp[i - zeroNum][j - oneNum] + 1. Then we go through the process of traversal , take dp[i][j] The maximum of . So the recurrence formula :dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1).
Compare the Standards 01 Knapsack problems will be found , A string of zeroNum and oneNum Equivalent to the weight of the article (weight[i]), The number of strings is equivalent to the value of the item (value[i]). This is a typical 01 knapsack ! It's just that the weight of an object has two dimensions .
The code implementation is as follows :
class Solution:
def findMaxForm(self, strs: List[str], m: int, n: int) -> int:
dp = [[0 for _ in range(n + 1)] for _ in range(m + 1)]
for s in strs:
oneNum, zeroNum = s.count("1"), s.count("0")
for i in range(m, zeroNum - 1, -1):
for j in range(n, oneNum - 1, -1):
dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1)
return dp[m][n]
It can be understood as having Two dimension Of a one-dimensional array 01 knapsack problem .
边栏推荐
- [PHP] tp6 multi table connection query
- Obvious things
- [MCU simulation] (XVII) control transfer instructions - call and return instructions
- [MCU simulation] (VI) addressing mode - index addressing and relative addressing
- Code demonstration of fcos face detection model in openvino
- Use RZ, SZ commands to upload and download files through xshell7
- RESNET learning notes
- ubuntu清除cuda缓存
- LETV has more than 400 employees? Living a fairy life without a boss, the official responded
- MySQL面试题(2022)
猜你喜欢

无线用的鉴权代码

SysTick定时器的基础学习以及手撕代码

Code demonstration of fcos face detection model in openvino

The place where the dream begins ---- first knowing C language
![[face recognition] face recognition based on histogram histogram with matlab code](/img/a6/ae776d084a207647501ca951e32000.png)
[face recognition] face recognition based on histogram histogram with matlab code

GraphQL初识

Configure high availability using virtual ip+kept

Visual analysis of ncnn param file and bin model

CorelDRAW 安装不了解决方法

Affine transformation implementation
随机推荐
Common MySQL commands you can use
Rtx3090 installing pytorch3d
[MCU simulation] (XIV) instruction system bit operation instructions - bit data transmission instructions MOV, bit variable modification instructions
Wechat applet
Ncnn mat matrix class
Obvious things
【剑指Offer】31-35题(判断一个序列是否是栈的出栈序列之一,层序打印二叉树以及分行打印、每行逆着打印),判断序列是否是二叉搜索树的后序遍历路径,二叉树找一条权值为K的路径,复制复杂链表
Zabbix6.0 monitors Dell and IBM server hardware through Idrac and imm2
GraphQL初识
Yolov5 ncnn reasoning
It's good to take more exercise
[MCU simulation] (VI) addressing mode - index addressing and relative addressing
Rhce8 Study Guide Chapter 2 use of basic commands
05-中央处理器
ncnn paramdict&modelbin
【模板记录】字符串哈希判断回文串
Net SNMP related commands
[MCU simulation] (VII) addressing mode - bit addressing
[MCU simulation] (XIX) introduction to assembly, assembly instructions, pseudo instructions
We should increase revenue and reduce expenditure