Complete knapsack problem (dynamic programming)

Complete knapsack problem

topic:

There are N kinds of goods and a backpack capacity of the V, each item has infinite element is available . The cost of goods is the i-th c [i], the value is w [i]. Solving the items into a backpack which allows the total cost of these items does not exceed the capacity of the backpack, and the sum of the maximum value.

 

 

First, verify the feasibility of dynamic Solver

 

This problem can not be the same as the 01 knapsack problem using dynamic programming to solve it? To prove what you can.

First, the first principle of optimality proof by contradiction:

Assuming complete backpack solution is F (n1, n2, ..., nN) (n1, n2 represent the first, the second select number of items), entirely subproblem backpack is, the front items into the i t backpack capacity and achieve maximum value, the corresponding solution is: F (n1, n2, ..., ni), assuming that the solution is not a sub-optimal solution, i.e., there is another set of solution F (m1, m2, ..., mi), making F (m1, m2, ..., mi)> F (n1, n2, ..., ni), then F (m1, m2, ..., mi ,. .., nN) must be greater than F (n1, n2, ..., nN), and therefore F (n1, n2, ..., nN) is not the optimal solution to the original problem, inconsistent with the null hypothesis, the F (n1 , n2, ..., ni) must be sub-optimal solution to the problem.

Let's look no after-effect:

For any solution of sub-problems, the solution subsequent sub-problems will not affect, that is, how kinds of goods before i choose, as long as the final bag space remaining unchanged, it will not influence the selection of items behind. That meet no after-effect.

Therefore, complete knapsack problem can also be solved using dynamic programming.

 

Second, the basic idea

 

This problem is very similar to the 01 knapsack problem, the difference is that each item has an infinite pieces. That it is, from the perspective of each item of consideration, associated with its policy was not to take or not take two types, but have to take 0, take one, take two ...... and so are many. If you are still thinking when the solution in accordance with 01 backpack, so  f [i] [v] represents the kinds of goods before i just put a maximum weight capacity of the backpack v. I can still write the state transition equation according to different strategies for each item:

State transition equation:

01 knapsack problem with this as there are  O (VN)   states need to solve, but each state has the solution time is not constant, and solving the status   f [i] [v]  of the time  , the overall complexity can be considered  , Shi Relatively large.

 

The basic code is as follows:


#include <iostream>
#include <algorithm>
#define N 1002
using namespace std;

int f[N][N];
int w[N];
int v[N];

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

 

State transition equation: 01 knapsack problem with the same full knapsack problem to optimize the spatial complexity [Theta] ( N ). 1.

After the spatial complexity optimized code as follows:


#include <iostream>
#include <algorithm>
#define N 1002
using namespace std;

int f[N];
int w[N];
int v[N];

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

Second, a simple and effective optimization

Complete knapsack problem has a very simple and effective optimization, is this: If two objects i, j meet   and   , j items will be removed, without regard. This optimization is clearly correctness: Under no circumstances can the high cost of small value j replaced by inexpensive i, at least not get worse solution. For randomly generated data, this method tends to greatly reduce the number of items, so that speed. This optimization can simply  [Theta] ( N 2 ) to achieve, generally can withstand.

However, this does not improve the worst-case complexity, because there may be special design of an item of data can be really stubborn. In addition, for purposes of knapsack problem, quite good method is: First, the cost of goods greater than V removed, then counted using a similar sort of approach to calculate the cost of the same items in the highest value which can be  [Theta] ( V + N ) to complete the optimization.

 

Third, translated into 01 knapsack problem solving 

Since the 01 knapsack problem is the most basic knapsack problem, then we can consider full 01 knapsack problem into a knapsack problem to solve. The simplest idea is that, given the i-th selected items up to   V / c [i]   pieces, so you can put items into the i-th   V / c [i]  piece cost and value are the same items, then solving this 01 knapsack problem.

This did not improve the complexity of the basic idea, but after all, gave us the full 01 knapsack problem into a knapsack problem thinking: An article will be split into multiple items.

More efficient transformation method is: the i-th split into cost items   , the value of   the plurality of items, wherein k satisfies    . This is binary thinking, because no matter the optimal policy option a few pieces of the i-th article, it can be expressed as the total number of  items and. Thus each of the articles is split into     items, is a great improvement.

 
 

Four, O (VN) algorithm

This algorithm uses a one-dimensional array, look at the pseudo-code:

for i=1..N
    for v=0..V
        f[v]=max{f[v],f[v-cost]+weight}
 

You will find that this pseudo-code and  01 pseudo-code knapsack problem only cyclic order v is different.

Why such a change can be OK it? First, think about why 01 knapsack problem in accordance with v = V..0 to reverse the cycle.

This is because the i-th cycle to ensure that in a state f [i] [v] is the state f [i-1] [vc [i]] Recursive from. In other words, this is to ensure that each item only once the election to ensure that in considering "opt-i-items" This strategy is based on a no member has been elected to the i-th result of sub-items f [ i-1] [vc [i]].

And now completely backpack features precisely when each item optional unlimited parts, so consider the "plus choose a i-th goods" such a strategy, but it is in need of a might have been elected to the i-th sub-items results f [i] [vc [i]], and so we must be v = 0..V loop sequence. This is why this simple procedure established truth.

 

It is worth mentioning that the above pseudo-code sequence for two cycles may be reversed. This conclusion is likely to bring on the optimization algorithm time constant.

This algorithm can also be drawn to other ideas. Explicitly write e.g., the basic idea of ​​solving f [i] [vc [i]] out the state transition equation, substituting into the original equation, may find that the equation becomes equivalent form of this form:

f[i][v]=max{f[i-1][v],f[i][v-c[i]]+w[i]}

This equation represents the meaning:

"The items put before i v backpack capacity of" the problem child, if only consider the strategy of the i-items (put the number), then it can be transformed into a problem only involves the items before i.

If you hold the i items, then the problem is transformed into "i-1 before the container is put items in a backpack v" value of F [i-1] [v];

If you put the first i items, then the problem is transformed into "before i items (i-1 before this is not the reason that the items here are infinite pieces, probably had already put the first i items) into the rest capacity of VC [i] backpack ", the maximum value of the backpack can be obtained at this time is f [i] [vc [i]] by placing value plus the value of w i obtained items [i] .

Code:


#include <iostream>
#include <algorithm>
#define N 1002
using namespace std;

int f[N];
int w[N];
int v[N];

int main() {
    int n,W; cin >> n >> W;
    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 <= W; j ++) {
            f[j] = max(f[j],f[j-w[i]] + v[i]);
        }
    }
    cout << f[W] <<endl;
    return 0;
}

 

Finally abstract pseudo code process a complete process Backpack articles:

procedure CompletePack(cost,weight)
    for v=cost..V
        f[v]=max{f[v],f[v-c[i]]+w[i]}
 
Published 118 original articles · won praise 63 · views 40000 +

Guess you like

Origin blog.csdn.net/qq_42185999/article/details/104499556