catalogue

# 1, Backpack introduction

Knapsack is actually dynamic programming, which can deduce the equation, but it is selected separately because it is common.

# 2, Backpack type

## 1.01 Backpack

Because he can only choose and not choose, he is compared to 01;

### 1. Two dimensional

Problem Description:

given n The weight of the article is weight，The corresponding value is value. Now select the items and put them into the backpack. It is assumed that the backpack can bear the maximum weight W by m，How to select the items to be loaded into the backpack to maximize the total value of the items loaded into the backpack?

order dp[i][w] represents the maximum value that can be obtained by putting the first I items into a backpack with a capacity of W. For convenience, we agree that the subscript starts from 1.

For item i:

- If it is selected, the maximum value of the current backpack is equal to "the value of item I" plus "the maximum value that the remaining backpack space can store after subtracting the space occupied by item I", that is, dp[i][k] = value[i] + dp[i-1][k-weight[i]];
- If it is not selected, the value of the current backpack is equal to the maximum value of the first i-1 items stored in the backpack, that is, dp[i][k] = dp[i-1][k]

Transfer equation:

dp(i,j) = max(dp(i-1,j),dp(i-1,j-w(i))+v(i));

The code implementation is as follows:

#include "iostream" #include "iomanip" using namespace std; //Optimal solution state space int dp[100][100]; int value[100]; int weight[100]; int n,m; int main(){ cin>>n>>m; for(int i=1;i<=n;i++) cin>>weight[i]>>value[i]; //Solving dp state recursively for (int i = 1; i <=n ; ++i) {//3 items for (int j = 1; j <=m ; ++j) {//Backpack space //If i item is not selected, the maximum is equal to dp[i-1][j] int without = dp[i-1][j]; //Selected i items: // First, there must be room for i items // Secondly, select the value of the item: the value of the current item + the maximum value of the remaining space int with = weight[i]<=j?dp[i-1][j-weight[i]]+value[i]:0; dp[i][j] = max(without,with); } } //Print dp status for (int i = 1; i <=n ; ++i) { for (int j = 1; j <=m ; ++j) { cout<<setw(m)<<dp[i][j]<<" "; } cout<<endl; } }

### 2. One dimension

We previously analyzed the state transition equation of 01 knapsack:

dp[i][k] = max(value[i] + dp[i-1][k-weight[i]], dp[i-1][k])

Observing the above code, we will find that when updating dp[i][k], it is only related to dp[i-1] [..], that is, we don't need to use O(n*W) space, but only O(W) space.

for (int i = 1; i <=n ; ++i) { for (int k = c; k >=1 ; k--) { //choose int value_with = (k - weight[i] >= 0) ? (dp[k - weight[i]] + value[i]) : 0; //Not selected int value_without = dp[k]; dp[k] = max(value_with,value_without); } }

The state transition equation here becomes:

dp[k] = max(value[i]+dp[k-weight[i]], dp[k])

## 2. Complete Backpack

# Problem description

have n The weight of each item is w[i]，Value is c[i]. Existing one with capacity of V How to select items to put into the backpack to maximize the total value of the items in the backpack. There are infinite items of each kind.

For the 01 knapsack problem, there are only two choices for each item: select and deselect. The transfer equation we derive is as follows:

dp[k] = max(value[i]+dp[k-weight[i]], dp[k])

In the complete knapsack problem, each item has unlimited items, that is, from the perspective of each item, the strategies related to it are not to choose or not to choose two, but: choose 0, choose 1, choose 2... And so on.

We use the idea of 01 knapsack problem for reference, calculate the results of each selection strategy, and then take the maximum value of all strategy states. The transfer equation is as follows:

Let dp[i][j] represent the maximum value of the first I items in the backpack with capacity j:

dp[i][j] = max{dp[i-1][j-k*weight[i]]+k*value[i]|0<=k*value[i]<=j}

Core code:

//Complete knapsack: solving dp state recursively for (int i = 1; i <=n ; ++i) {//goods for (int j = 1; j <=c ; ++j) {//Backpack space //All strategies need to be calculated here, corresponding to 01 knapsack problem. Only two strategies, select and deselect, need to be calculated here for (int k = 0; k*weight[i] <= j ; ++k) { dp[i][j] = max(dp[i][j],dp[i-1][j-k*weight[i]]+k*value[i]); } } }

# 3, Examples

## 1. Jin Ming's budget plan

Details: Jinming's budget plan Victor's blog - CSDN blog

As we know from the title, a main part can have two accessories at most, and the main part must be purchased first, so:

1. Select only the main part and no accessories: dp[j]=max(dp[j],dp[j-w[i]]+v[i]);

2. Select the main part and the first accessory: dp[j]=max(dp[j],dp[j-w[i]-w1[i][1]]+v[i]+v1[i][1]);

3. Select the main part and the second accessory: dp[j]=max(dp[j],dp[j-w[i]-w1[i][2]]+v[i]+v1[i][2]);

4. Select main parts and all accessories: dp[j]=max(dp[j],dp[j-w[i]-w1[i][1]-w1[i][2]]+v[i]+v1[i][1]+v1[i][2]);

## 2. Machine allocation

The head office has M sets of efficient equipment, which is ready to be distributed to N subordinate branches. If each branch obtains these equipment, it can provide certain profits for the country.

Q: how to allocate this M equipment to maximize the profit of the country? Calculate the maximum profit value, where m ≤ 15 and N ≤ 10.

Distribution principle: each company has the right to obtain any number of equipment, but the total number does not exceed M.

Input format:

The input contains a set of data: the first row has two numbers, the first is the number of branches N, and the second is the number of equipment M.

Next is an N*M matrix, which shows the profit of J machines allocated by the I company.

Output format:

Output the maximum profit value of the first behavior;

Next, there are n lines for the number of machines allocated by each branch.

Limitations:

Space limit: 128MByte

Time limit: 1 second

Example:

Input: 3

30 40 50

20 30 50

20 25 30

Output:

70

1 1

2 1

3 1

Tips:

The minimum dictionary order of the answers is required

#include<iostream> using namespace std; int n,dp[20][20],m,v[20][20],sum[20][20]; void print(int i,int j){ if(i==0) return; print(i-1,j-sum[i][j]); cout<<i<<" "<<sum[i][j]<<endl; } int main() { cin>>n>>m; for(int i=1; i<=n; i++) for(int j=1; j<=m; j++) cin>>v[i][j]; for(int i=1; i<=n; i++) for(int j=1; j<=m; j++) for(int k=0; k<=j; k++) if(j>=k) if(dp[i][j]<dp[i-1][j-k]+v[i][k]) { dp[i][j]=dp[i-1][j-k]+v[i][k]; sum[i][j]=k; } cout<<dp[n][m]<<endl; print(n,m); return 0; }