One backpack dynamic programming of talk nine --01 backpack

Before explaining our first look at a topic. As follows:
a thief has a maximum receiving kg backpack M, N have now store items, the weight of each item are w1, w2, ... wn. The value of each item is v1, v2, ..., vn. Seek the greatest value of a thief can steal. (Where M <= 200 is, n-<= 30) .
The first input line M, n. The second row to row 1 + n, one per line and a weight value, representative of the i-th items of information.

This question is a typical knapsack problem, analysis shows that without the backing of the package burst, select the appropriate items, total value is maximized.
Since this topic is the dynamic programming, dynamic programming and there are four steps are: ① determine the status of the transfer equation ② ③ ④ initial conditions and critical circumstances the order of evaluation we now begin the first step to determine the state. As the name implies, determines the state that is to determine the meaning of the expression of our representatives, we first open up a two-dimensional array dp [i] [j] maximum value represents the first i items, the current capacity of the backpack j, available to .
The second step is the most important transfer equation, popular point that recurrence relations. For each item, only two cases, the first case is greater than the current capacity of the backpack Weight an article, i.e. it can be installed under the current items. The second situation is that the current capacity is less than an item backpack weight, which is fit. So for the second case, we have no choice. As the saying goes ideal is full, the reality is very skinny, even if you want to dominate the martial arts, but nonetheless powerful enough ah ~ ~. In the first case it then, when you have enough space, the initiative will be in our hands, we can decide to take or not take. If you do not take, then the result is equivalent to the case take no less than. If you take, it is necessary to remove the current weight of these items in a backpack, that is the maximum value with a backpack after lose weight corresponding to the current capacity plus the value of these items . (Note: Be sure to keep in mind, dp [i] [j] mean anything, but do not be too focused on its variable letters i, j represents what.)
Therefore, according to an analytical study of recurrence relations as follows:
dp [i ] [j] = max (dp [i] [j], dp [i - 1] [j - w [i]] + v [i])
The third step is it? Initial conditions, what are the initial conditions? Popular talk is the first number, for the present problem is that when i = 0, dp [i] [j] = 0, when j = 0, dp [i] [j] = 0. Corresponding practical significance: When the first item that is not 0 items, of course, the value is zero. When 0 knapsack capacity is, of course, fit anything, the value is still 0.
OK, after completed the most difficult step, we began to give Code:
preliminary version: time complexity: O (the n- 2 )

#include<iostream>
#include<algorithm>
using namespace std;
int dp[40][210], w[40], v[40];
int main()
{
	int n, M;
	cin >> M >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> w[i] >> v[i];
	}
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= M; j++)
		{
			if (j < w[i])
				dp[i][j] = dp[i - 1][j];
			else
				dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i]] + v[i]);
		}
	}
	cout << dp[n][M];
	return 0;
}

Appendix: Initial Conditions previously thought, it corresponds to the code is initialized to 0, i = 1 from the start through the loop.

I believe we have seen the words in front of the primary version, yes, since there are preliminary version, then there will be an advanced version. Here enter the optimal solution to the problem.

In the previous analysis we can know, when you face the first i items, no matter what you decide, you have contact with on an item, without contact with other items, this is the principle of the invalidity of the problem . Corresponds to the code can be verified.

			if (j < w[i])
				dp[i][j] = dp[i - 1][j];
			else
				dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i]] + v[i]);

We assume that the data input is as follows:
10. 4
2. 1
. 3. 3
. 4. 5
. 7. 9

In fact, this two-dimensional array of values ​​we can print it every time the outer loop. I have a good print, as follows.

Line: The first column of several items: backpack capacity
Here Insert Picture Description
after invalid according to the principle, and we need the final results of the last obtained results, so we can give up to obtain the front. We can be compressed into a two-dimensional array array, an array of fundamental principle is rolling . That is when you find one of the first data row i + 1, the data do not need to write the result of the first row i + 1, only need to replace the old data on the original i-th row. So the cycle, you can reach the outer loop is updated each time the effect of stripes again . (Very important ideas)
then we had the idea to quickly upgrade to do about it, got the following code:

#include<iostream>
#include<algorithm>
using namespace std;
int dp[210], w[40], v[40];
int main()
{
	int n, M;
	cin >> M >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> w[i] >> v[i];
	}
	for (int i = 1; i <= n; i++)
	{
		for (int j = w[i]; j <= M; j++)
		{
			dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
		}
	}
	cout << dp[M];
	return 0;
}

Then we went again submit OJ platform, then found the problem. The results do not! ! Why is this? Most people here are the most difficult to understand where this thinking of migrating from a two-dimensional array directly over, but in fact it was an error. We are conducting in-depth analysis below. Chart observed:
(orange arrow & arrow blue as a set, a green arrow is a group & black arrow)
Here Insert Picture Description
to result in a yellow region 8, in accordance with the transfer equation known, by the starting point of the orange arrows 4 and the starting point plus the blue arrow 3 the value of the article corresponding to the total value is equal to 8 5 Comparative get out of 8> 4, 8 Heaven so the yellow region. The same applies to the blue area. Look transfer equation dp [i] [j] = max (dp [i] [j], dp [i - 1] [j - w [i]] + v [i]) find dp [i - 1] [j - w [i]] of the second index is always less than dp [i] [j] of the second index (since subtraction). Corresponds to the form that it is in each comparison data after the number of the base point, and in front of it a number of comparison, then the result of comparison to the point where the update. Then there will be a problem. Is more direction from back to front, or more direction from the front to the rear of? (Note that the direction of comparison is the general direction, to compare the two numbers, the number will always be behind the point, do not confuse this direction)
Focus:
Because it is constantly refreshed data in a one-dimensional array, and we also need to use when comparing old data (i-1 is the first data row in the two-dimensional array), then compare if the direction from front to back, the data will serve as a basis to update, this point is called a temporary point a, but this time with respect to the base point is compared to another number in the back. When you then compare the next rounds, when the A point as the numbers are compared for (relatively in the new round, it is not a point, but as numbers are comparable basis points), the actual need is old data A value of the point, but in front of you for a round in comparison, has taken the old data point a to update, and now point a is stored in the new data. This will result in data coverage, data back from the beginning is wrong. It is not feasible in this direction.
In addition there is only a relatively direction, and from back to front. For this direction, because the figures after another comparison is in the back, so every time data updates basis points basis points relative to this point will not be used in comparing the latter, then the whole round of comparison the data obtained will not be covered happen.
Senior correct version of the code as follows :

#include<iostream>
#include<algorithm>
using namespace std;
int dp[210], w[40], v[40];
int main()
{
	int n, M;
	cin >> M >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> w[i] >> v[i];
	}
	for (int i = 1; i <= n; i++)
	{
		for (int j = M; j >= w[i]; j--)
		{
			dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
		}
	}
	cout << dp[M];
	return 0;
}

It is the wrong version of the above the only difference is the change in direction of the inner loop.

So far, 01 knapsack problem of all solutions, progressive approach to explain all finished. Follow-up will also update other branches knapsack problem, if you like the point of a praise chant. thank you all.

ps: bloggers limited capacity, if the reader finds any questions, comments or private letter points out the shortcomings. Readers are welcome to ask questions, happy to do my best to answer reader questions. Comments welcome, welcome exchange. thank you all!

Published 46 original articles · won praise 10 · views 977

Guess you like

Origin blog.csdn.net/lyqptp233/article/details/104892176