Dynamic Programming - knapsack problem python implement (01 backpacks full backpack, multiple backpack)

reference:

Backpack nine stresses - Bilibili

Backpack nine stresses



01 knapsack problem

01 knapsack problem

description:

There are N items V and a capacity of the backpack.

Volume is the i-th items vi, a value wi.

What will solve the items into a backpack, the total volume of these items can not exceed backpack traffic, and the total value of the maximum.


Two-dimensional dynamic programming

F [i] [j] denotes the i-th item look front, where j is the total volume, the total value is the largest number. result = max (f [n] [0 ~ V]) f [i] [j]:

  • The i-th item is not selected: f [i] [j] = f [i-1] [j];

  • Selected from the i-th items: f [i] [j] = f [i-1] [jv [i]] + w [i] (v [i] is the i th volume of the article) between the maximum take . Initialization: f [0] [0] = 0 (and consequently do not choose the circumstances, no matter how much capacity, are 0?)

code show as below:

n, v = map(int, input().split())
goods = []
for i in range(n):
    goods.append([int(i) for i in input().split()])

# 初始化,先全部赋值为0,这样至少体积为0或者不选任何物品的时候是满足要求  
dp = [[0 for i in range(v+1)] for j in range(n+1)]

for i in range(1, n+1):
    for j in range(1,v+1):
        dp[i][j] = dp[i-1][j]  # 第i个物品不选
        if j>=goods[i-1][0]:# 判断背包容量是不是大于第i件物品的体积
            # 在选和不选的情况中选出最大值
            dp[i][j] = max(dp[i][j], dp[i-1][j-goods[i-1][0]]+goods[i-1][1])


print(dp[-1][-1])


One-dimensional dynamic optimization

Two-dimensional view from above, f [i] only [i-1] associated with f, so using only a one-dimensional array [0 ~ v] to store the previous state. So how to achieve it?

The first question: the state transition

Dp assume an array of storage on a state, then there should be:

dp[i] = max(dp[i] , dp[i-v[i]]+w[i])

inside the function max dp [i] represents the value of a state.

The second question: Initialization

Here starts initializing a length of one-dimensional array V + 1, 0 when the selected item, the volume of the maximum value at 0 ~ V (values ​​are all 0).

The third question: recurrence relations

Imagine, I make sure to strike when the i-th state, use the value of a one-dimensional array is the first i-1 states. If I push from front to back, so when I traversed back, I used the i-th state is the state rather than the first i-1 states. such as:

dp[i] = max(dp[i] , dp[i-v[i]]+w[i])

Where dp [iv [i]] that has been re-assigned, a state rather than the value, this is wrong. Therefore, we must push forward from the back .

n, v = map(int, input().split())
goods = []
for i in range(n):
    goods.append([int(i) for i in input().split()])

dp = [0 for i in range(v+1)]

for i in range(n):
    for j in range(v,-1,-1): # 从后往前
        if j >= goods[i][0]:
            dp[j] = max(dp[j], dp[j-goods[i][0]] + goods[i][1])

print(dp[-1])


Determining the volume of the case

If not, I ask the greatest possible value, but the capacity is just equal to the maximum value of the backpack, then how to do it?


Complete knapsack problem

Complete knapsack problem

description:

There are N items V and a capacity of the backpack, each item has unlimited! .

Volume is the i-th items vi, a value wi.

What will solve the items into a backpack, the total volume of these items can not exceed backpack traffic, and the total value of the maximum.


One-dimensional dynamic programming

Complete knapsack problem knapsack problem with the 01 biggest difference is that each item can be selected many times, so when we take into account the i-th article, we should consider is: do not choose this item, choose this time items, the election twice ...... this article, can not be selected until the (selected number k, k * v [i]> j, j backpack current capacity), then select the maximum from those circumstances. code show as below:

n, v = map(int, input().split())
goods = []
for i in range(n):
    goods.append([int(i) for i in input().split()])
dp = [0 for i in range(v+1)]
for i in range(n):
    for j in range(v,-1,-1): # 从后往前
        k = j//goods[i][0]  # 能选多少次
        # 从这些次里面取最大
        dp[j] = max([dp[j- x* goods[i][0]] + x * goods[i][1] for x in range(k+1)])

print(dp[-1])


One-dimensional dynamic programming (optimization)

Just that question, we are the continuation of 01 knapsack problem, recursive forward from the back. But for that matter, in fact, be back by the recurrence past. How to understand it?

Suppose the state when considering two i-th items:

A:dp[k*v[i] + x]

B:dp[(k-1)*v[i] + x]

The foregoing induction, over the previous state of the recursive:

  • A requirement value of k + 1 should be from the selected largest states:

    dp[x] + k*w[i]
    dp[v[i] + x] + (k-1)*w[i]
    dp[2*v[i] + x] + (k-2)*w[i]
    ...
    ...
    dp[(k-1)*v[i] + x] + w[i]
    dp[k*v[i] + x
  • Required value of B should be selected from the k largest state:

    dp[x] + (k-1)*w[i]
    dp[v[i] + x] + (k-2)*w[i]
    dp[2*v[i] + x] + (k-3)*w[i]
    ...
    ...
    dp[(k-2)*v[i] + x] + w[i]
    dp[(k-1)*v[i] + x

We can see that over one-word, two states actually're just one w [i] values. therefore:

While we can (i-1) in accordance with the state at this time is introduced before a state, on the other hand because the current value of the current sub-problem is the problem of the foregoing state, so we can be pushed from the previous value to the latter value.

Front to back recursive code is as follows:

n, v = map(int, input().split())
goods = []
for i in range(n):
    goods.append([int(i) for i in input().split()])
dp = [0 for i in range(v+1)]
for i in range(n):
    for j in range(v+1):
        if j >= goods[i][0]:
            dp[j] = max(dp[j], dp[j-goods[i][0]] + goods[i][1])

print(dp[-1])

Multiple Knapsack Problem

Multiple Knapsack Problem

description:

There are N items V and a capacity of the backpack.

Volume of the i items is vi, the value of wi, a number si.

What will solve the items into a backpack, the total volume of these items can not exceed backpack traffic, and the total value of the maximum.


One-dimensional dynamic programming

In fact, with the full knapsack problem similar to the above, but we move forward from the recursive when i select the number of objects should be reconsidered at:

k = min(s[i], j//v[i]), j为当前的背包容量

code show as below:

n,v = map(int, input().split())
goods = []
for i in range(n):
    goods.append([int(i) for i in input().split()])

dp = [0 for i in range(v+1)]

for i in range(n):
    for j in range(v, -1, -1):
        # 考虑两种情况的最小值
        k = min(j//goods[i][0], goods[i][2])
        dp[j] = max([dp[j-x*goods[i][0]] + x*goods[i][1] for x in range(k+1)])

print(dp[-1])


One-dimensional dynamic programming (conversion 01 backpack)

The idea is simple, directly to the backpack of items to expand, develop into a lot of quantity of items 1, thus converted into 01 knapsack problem. code show as below:

n,v = map(int, input().split())
goods = []
for i in range(n):
    goods.append([int(i) for i in input().split()])

new_goods = []

# 展开
for i in range(n):
    for j in range(goods[i][2]):
        new_goods.append(goods[i][0:2])

goods = new_goods
n = len(goods)

# 01背包问题
dp = [0 for i in range(v+1)]

for i in range(n):
    for j in range(v,-1,-1):
        if j>= goods[i][0]:
            dp[j] = max(dp[j], dp[j - goods[i][0]] + goods[i][1])

print(dp[-1])

Guess you like

Origin www.cnblogs.com/anzhengyu/p/11408466.html