# 01 knapsack problem backtracking and dynamic programming solution

Posted by tsinka on Thu, 28 Oct 2021 16:47:20 +0200

# Problem description

Description

A traveler has a backpack that can hold up to m kg. There are n items. Their weights are w1,w2,w3,...,wn respectively, and their values are c1,c2,c3,...,cn respectively. If there is only one item of each kind, seek the maximum total value that the traveler can obtain.

Input

m. And n (m < = 200, n < = 30)
Next, there are n lines, with two integers wi,ci in each line

Output

Maximum total value

Sample Input

10 4 2 1 3 3 4 5 7 9

Sample Output

12

# Backtracking method

### Data definition

```int m;//Backpack Capacity
int n;//Number of items
int weight[30];
int value[30];
int MaxValue = 0;//Maximum value

int NowWeight = 0;//Current weight
int NowValue = 0;//Current value```

### node

Take the ith item as a node and the (i+1) th item as its son node. The left and right subtrees represent the situation of putting and not putting the ith item respectively

### Constraint function

When the remaining capacity of the knapsack is not enough to put the i-th item, there can be no solution to the problem under the left subtree, so the traversal of the left subtree is terminated by the pruning function

```//The constraint function returns whether the ith item can be put into the backpack
bool CheckWeight(int i) {
if (NowWeight + weight[i] > m) {
//overweight
return false;
} else{
//Can put
return true;
}
}```

### Backtracking method

Before traversing the left subtree of I, first judge whether the i-th item can be put in. If so, try to put it in. After traversing the left subtree, take out the i-th item and traverse the right subtree

```void Search(int i) {
//i is out of range, indicating that DFS has been completed once
if(i == n){
//Update maximum value
if(NowValue > MaxValue){
MaxValue = NowValue;
}
return;
}
//If you can put the ith item, try traversal
if(CheckWeight(i)){
//Try to put the i-th item
NowWeight += weight[i];
NowValue += value[i];
//Traversing the subtree of i
Search(i + 1);
//Take out the i-th item
NowWeight -= weight[i];
NowValue -= value[i];
}
//This is to traverse the subtree without putting the i-th item
Search(i + 1);
}```

### Complete code

```#include <iostream>

using namespace std;

int m;//Backpack Capacity
int n;//Number of items
int weight[30];
int value[30];
int MaxValue = 0;//Maximum value

int NowWeight = 0;//Current weight
int NowValue = 0;//Current value

void Search(int i);

int main() {
scanf("%d%d", &m, &n);
for (int i = 0; i < n; i++) {
scanf("%d%d", &weight[i], &value[i]);
}
Search(0);
printf("%d",MaxValue);
return 0;
}

//The constraint function returns whether the ith item can be put into the backpack
bool CheckWeight(int i) {
if (NowWeight + weight[i] > m) {
//overweight
return false;
} else{
//Can put
return true;
}
}

void Search(int i) {
//i is out of range, indicating that DFS has been completed once
if(i == n){
//Update maximum value
if(NowValue > MaxValue){
MaxValue = NowValue;
}
return;
}
//If you can put the ith item, try traversal
if(CheckWeight(i)){
//Try to put the i-th item
NowWeight += weight[i];
NowValue += value[i];
//Traversing the subtree of i
Search(i + 1);
//Take out the i-th item
NowWeight -= weight[i];
NowValue -= value[i];
}
//This is to traverse the subtree without putting the i-th item
Search(i + 1);
}```

# Dynamic programming method

### Problem decomposition

Two parameters are needed to judge the current state of the backpack. The first is "remaining capacity", which can determine how many items can be put in the backpack; the second is "item serial number", which determines which items will be put in the backpack

With these two parameters, the state of the backpack can be uniquely determined, so the maximum value that the backpack can achieve in this state can be obtained

### State function

Define the function GetMaxValue(int capacity, int i). The parameters are the status parameters mentioned above. The return value of the function is the maximum value that the knapsack can achieve in this state

### state transition

The maximum value with or without item i is related to the maximum value with or without item (i+1)

If you put it into the backpack, the capacity of the backpack decreases and the value of the backpack increases. At this time, the value is

`GetMaxValue(capacity + weight[i],i+1) + value[i]`

If the backpack is not put in, the capacity and value of the backpack remain unchanged, and the maximum value when returning directly to (i+1)

`GetMaxValue(capacity,i+1)`

Take the larger of the two

```//Returns the maximum value when the current capacity is capacity and whether to put in item i
int GetMaxValue(int capacity, int i){
if(i >= n || capacity >= m) return 0;
if(capacity + weight[i] > m){
//If the item i cannot be put, return the maximum value of whether to put the item (i+1)
return GetMaxValue(capacity,i+1);
} else{
//If the item i can be placed, calculate the situation of putting in and not putting in the item i respectively, and return the larger value
return Max(GetMaxValue(capacity + weight[i],i+1) + value[i], GetMaxValue(capacity,i+1));
}
}```

### Save results

In order to avoid repeated calculation, save the results of each calculation to the array. If you encounter the same state next time, you can directly return the results (the effect is not obvious in this problem)

```int f[200][30];//Record the results of each operation

//Returns the maximum value when the current capacity is capacity and whether to put in item i
int GetMaxValue(int capacity, int i){
if(i >= n || capacity >= m) return 0;
//If this status has been calculated, the result is returned directly
if(f[capacity][i] != -1) return f[capacity][i];
//If the status has not been calculated, first judge whether the item can be put down i
if(capacity + weight[i] > m){
//If the item i cannot be put, return the maximum value of whether to put the item (i+1)
f[capacity][i] = GetMaxValue(capacity,i+1);
} else{
//If the item i can be placed, calculate the situation of putting in and not putting in the item i respectively, and return the larger value
f[capacity][i] = Max(GetMaxValue(capacity + weight[i],i+1) + value[i], GetMaxValue(capacity,i+1));
}
return f[capacity][i];
}```

### Complete code

```#include <iostream>

using namespace std;

int m;//Backpack Capacity
int n;//Number of items
int weight[30];
int value[30];

int f[200][30];//Record the results of each operation

int GetMaxValue(int capacity, int i);

int main() {
for(auto & i : f){
for(int & j : i){
j = -1;
}
}
scanf("%d%d", &m, &n);
for (int i = 0; i < n; i++) {
scanf("%d%d", &weight[i], &value[i]);
}
printf("%d\n", GetMaxValue(0,0));
return 0;
}

int Max(int a,int b){
return a>b?a:b;
}

//Returns the maximum value when the current capacity is capacity and whether to put in item i
int GetMaxValue(int capacity, int i){
if(i >= n || capacity >= m) return 0;
//If this status has been calculated, the result is returned directly
if(f[capacity][i] != -1) return f[capacity][i];
//If the status has not been calculated, first judge whether the item can be put down i
if(capacity + weight[i] > m){
//If the item i cannot be put, return the maximum value of whether to put the item (i+1)
f[capacity][i] = GetMaxValue(capacity,i+1);
} else{
//If the item i can be placed, calculate the situation of putting in and not putting in the item i respectively, and return the larger value
f[capacity][i] = Max(GetMaxValue(capacity + weight[i],i+1) + value[i], GetMaxValue(capacity,i+1));
}
return f[capacity][i];
}```

Topics: Algorithm Dynamic Programming