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]; }