Dynamic programming: 0-1 knapsack problem (C++)

Dynamic programming: 0-1 knapsack problem

The general steps of dynamic programming:

  1. Problem structure analysis
  2. Recursive relationship establishment
  3. Bottom-up calculation
  4. Best solution tracking

Example 0-1 knapsack problem

(Subject source: https://www.acwing.com/problem/content/description/2/)

Title description
There are N items and a backpack with a capacity of V. Each item can only be used once.

Volume of the items is i V i , is the value of W i .

Find out which items to load into the backpack so that the total volume of these items does not exceed the backpack capacity and the total value is the largest.
Output the maximum value.

Input format
Two integers N and V in the first line, separated by spaces, respectively indicate the number of items and the volume of the backpack.

Then there are N rows, each row two integers V i , W i , separated by spaces, respectively, and the volume of the i-th value of the items.

Output format
Output an integer that represents the maximum value.

Data range
0<N,V≤1000
0<vi,wi≤1000

Input example
4 5
1 2
2 4
3 4
4 5

Sample output
8

Problem analysis
In the case of a certain size of the backpack, find the highest value of the total value, each item has only two cases of selection and no selection, and compare the total value of the two cases.

f[i][j] means only look at the first i items. If the total volume is j, what is the maximum total value.
result = max{f[n][0~V]}

f[i][j]:
1. Do not choose the ith item, f[i][j] = f[i-1][j];
2. Choose the ith item, f[i][j] = f[i-1][jv[i];

Choose the largest and most in two cases: f[i][j] = max{1,2}

Initialization: f[0][0] = 0;

Insert picture description here

Code 1

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1010;
int n,m;	//n表示物体个数,m表示背包容量 
int f[N][N]; 
int v[N], w[N]	//v[N], w[N] 分别表示每个物品的体积和价值 

int main(){
    
    
	cin >> n >> m;
	for(int i=0; i<n; i++){
    
    
		cin >> v[i] >> w[i];
	}
	for(int i=1; i<=n; i++)
		for(int j=1; j<=m; j++){
    
    
			f[i][j] = f[i-1][j];
			if(j >= v[i])
				f[i][j] = max(f[i][j], f[i-1][j-v[i]] + w[i]);
		} 
		
	int res = 0;
	for(int i=0; i<=m; i++)
		res = max(res,f[n][i]);
		
	cout << res << endl;
	return 0;
} 

f[N][N]Optimize on the basis of the two-dimensional array , and optimize the two-dimensional array f[N][N]to f[N]indicate the maximum value of the first i items when the backpack volume is j; f[m] must be updated every time the outer loop is performed;
Insert picture description here

Code 2

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1010;
int n,m;	//n表示物体个数,m表示背包容量 
int f[N]; 	//表示背包体积为j时前i个物品的最大价值为多少 
int v[N], w[N]	//v[N], w[N] 分别表示每个物品的体积和价值 

int main(){
    
    
	cin >> n >> m;
	for(int i=0; i<n; i++){
    
    
		cin >> v[i] >> w[i];
	}
	for(int i=1; i<=n; i++)
		for(int j=m; j>=v[i]; j--){
    
    
			f[j] = max(f[j], f[j-v[i]] + w[i]);		//f[j]滚动记录最优解 
		} 
		
	cout << f[m] << endl;	
	return 0;
} 

Guess you like

Origin blog.csdn.net/qq_44524918/article/details/108992114