Dynamic planning---01 backpack/complete backpack

The previous blog talked about the introduction of dynamic programming. Today, let’s take a look at a branch of dynamic programming, 01 backpack;

01 backpack problem

Why, call him 01 backpack, as the name suggests, his state is only 0 or 1; that is, take or not;
international practice, use a question to explain;
Luogu P1048-picking herbs
Insert picture description here

Now he needs to know what kind of medicine to take will make the most valuable;
suppose, we now think according to the sample of the question;
Insert picture description here

Now we have 70 available time; the left column represents the time of different medicine collection, the upper row represents the size of the backpack;

First of all, in the first line, since 71>70, no matter which state, the value of our medicine collection is 0;

Insert picture description here

Then look at the second row. At the beginning, the weight of the backpack is increased from 1. Therefore, when the size of the backpack is less than 69, the capacity of the backpack is not enough to put the medicine. When the backpack is greater than or equal to 69, the value of the medicine collection is 1;
Insert picture description here

Look at the next line again, when the weight of the backpack is 1, the maximum value that can be generated by collecting the medicine is 2; after that, it keeps pushing backward
Insert picture description here

At this time, when the backpack size is 69, we have two choices, one is to take 1 but not 69, and the other is to take 69 but not 1. Obviously, the value of 1 is greater;

When the backpack is 70, we can either get 1 or 69, and the maximum value at this time is 3;

Insert picture description here

Therefore, for an item, we can choose to take or not to determine its own value, we use a two-dimensional array dp to represent;
w[i] represents the weight of each item, v[i] represents the value of the item ;

int dp[i][j] represents the maximum value when the size of the backpack is j for the i-th item;
at this time, for i, if the size of the backpack is enough to hold this item (j>=w[i] ), then
dp[i]j[j] is the state of the previous item (dp[i-1][j]) plus the value of this item v[i]. At the same time, the size of the backpack is also To reduce w[i] (dp[i-1][jw[i]]);

即,dp[i][j]=max{dp[i-1][j-w[i]]+v[i],dp[i-1][j]}

If the size of the backpack cannot fit this item at this time, then dp[i][j]=dp[i-1][j];

The main core code is:

for (int i = 1; i <= m; i++)
        for (int j = t; j >= 0; j--)
        {
    
    
            if (j >= w[i])
            {
    
    
                dp[i][j] = max(dp[i - 1][j - w[i]] + v[i], dp[i - 1][j]);
            }
            else
            {
    
    
                dp[i][j] = dp[i - 1][j];
            }
        }

The complete source code of this question is as follows;

#include<iostream>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
int dp[105][1005];
int w[105], v[105];
int main()
{
    
    
    int m,t;
    cin >> t >> m;
    for (int i = 1; i <= m; i++)
    {
    
    
        cin >> w[i]>> v[i];
    }
    for (int i = 1; i <= m; i++)
        for (int j = t; j >= 0; j--)
        {
    
    
            if (j >= w[i])
            {
    
    
                dp[i][j] = max(dp[i - 1][j - w[i]] + v[i], dp[i - 1][j]);
            }
            else
            {
    
    
                dp[i][j] = dp[i - 1][j];
            }
        }
    cout << dp[m][t];
    return 0;
}

Look at a deformed version of Luogu's 01 backpack;
Insert picture description here

The difference between this question and the above is that his state has winning and losing, and both winning and losing will increase the experience value;
so this state transition equation becomes;

dp[j]=max(dp[j-use[i]]+win[i],dp[j]+lose[i]);

The complete code is as follows;

#include<bits/stdc++.h>
using namespace std;
long long use[1005],win[1005],lose[1005];
long long dp[1005];
int main()
{
    
    
	long long n,x;
	cin>>n>>x;
	for(int i=1;i<=n;i++)
	{
    
    
		cin>>lose[i]>>win[i]>>use[i];
	}
	for(int i=1;i<=n;i++)
	{
    
    
		for(int j=x;j>=0;j--)
		{
    
    
			if(j>=use[i])
			{
    
    
				dp[j]=max(dp[j-use[i]]+win[i],dp[j]+lose[i]);
			}
			else
			{
    
    
				dp[j]=dp[j]+lose[i];
			}
		}
	}
	cout<<dp[x]*5;
	return 0;
 } 

01 Optimization of backpack;

As mentioned above, the 01 backpack needs a two-dimensional array to record the corresponding state, but the two-dimensional array is easy to have MLE;

So there is the 01 knapsack of a one-dimensional array;
from the above we can see that dp[i] is completely derived from dp[i-1];
so we only need to use a one-dimensional array of dp[j] , Complete this question by updating the maximum value each time; the
specific code is as follows:

 for(int i=1;i<=m;i++) 
    {
    
    
        for(int j=t;j>=0;j--) 
        {
    
    
            if(j>=w[i])
            {
    
    
                dp[j]=max(dp[j-w[i]]+v[i], dp[j]);
            }
        }

This greatly reduces the memory usage;

Complete backpack

The difference between the full backpack and the 01 backpack is; the 01 backpack can only be taken or not, while the full backpack can be taken all the time.
Therefore, his core code has a little transformation compared to the 01 backpack.

for(int i = 1;i <= m;i ++){
    
    
		for(int j = w[i];j <= T;j ++){
    
    
			f[j] = max(dp[j],dp[j - w[i]] + v[i]);
		}

For example, the following question, you can completely apply this template
Insert picture description here

#include<iostream>
#include<algorithm>
using namespace std;
const int maxm = 10010, maxt = 10000010;
long long v[maxm], t[maxm], f[maxt];
int main(){
    
    
	int T , m;
	cin >> T >> m;
	for(int i = 1;i <= m ;i ++) cin >> t[i] >> v[i];
	for(int i = 1;i <= m;i ++){
    
    
		for(int j = t[i];j <= T;j ++){
    
    
			f[j] = max(f[j],f[j - t[i]] + v[i]);
		}
	}
	cout << f[T];
}

Guess you like

Origin blog.csdn.net/weixin_52313562/article/details/114187949