[01] learning algorithm knapsack problem

Source algorithm is practical courses Mu class network - Dynamic Programming

01 knapsack problem

01 backpack
It is equivalent to seeking a combination of n items!
Violence solution:
each item, you can put in a backpack, you can not put. Complexity is O ((2 ^ n) * n), for each combination, we have to see how much the total weight corresponds to see if it is more than the capacity C, so that the Value.

Combinations can be solved by recursively. But it is able to find overlapping subproblems, optimal substructure, whereby the conversion is DP.

Design:
Status: state prior to use a parameter to solve the problem, the problem is usually the number of parameters means that constraints to solve the problem needs to be met.
This problem two constraints, the first from the n items in the election, and then the capacity to meet ≤C, thus: state (function) is
F. (N, C) of n items into consideration the capacity of the backpack C, such that The maximum value.

State transition : F. (I, C) = F. (I-1, C)
= V (i) + F. (I-1, CW (i)) into the consideration of the foregoing items i-1 th
for the i th or not in the end article to be put into the backpack, select one of the two max
state transition equation : F (i, c) = max (F (i-1, c), v (i) + F (i-1, cw (i)))
a lot of dynamic programming can be used similar to the above ideas!

Write code: still first top-down, bottom-up and then transform into
a recursive manner:

class 
Knapsack01 {
private:
    // 用[0,...index]的物品,来填充容积为c的背包的最大值
    int bestValue(const vector<int> &w, const vector<int> &v, int index, int c){

        // 无法选物品 or 装不下物品,都无价值
        if(index < 0 || c<=0)  
            return 0;

        int res = bestValue( w, v, index-1, c);
        // 检查一下容积C
        if( c >= w[index])
            res = max(res, v[index] + bestValue(w,v,index-1, c-w[index]) );

        return res;
    }

public:
    int knapsack01(const vector<int> &w, const vector<int> &v, int C ){

        int n = w.size();

        return bestValue(w, v, n-1, C); //考虑从0-n-1的n个物品,装入C
    }
    
};

Recursively using memory search +:
format
overlapping subproblems: index c and constitute the data, such data may be the way to solve the same data multiple times, it may be used for this memory search during the solution process.
Because there are two constraints knapsack problem, each state is defined as two variables, open space is two-dimensional array of memory! - Vector <Vector> Memo (n, Vector (C + 1, -1));
Memo has n rows, each row is a Vector, a total of C + 1 column

private:
    vector<vector<int>> memo;
    // 用[0,...index]的物品,来填充容积为c的背包的最大值
    int bestValue(const vector<int> &w, const vector<int> &v, int index, int c){

        // 先判断有无值
        if(memo[index][c] != -1)
            return memo[index][c];

        // 无法选物品 or 装不下物品,都无价值
        if(index < 0 || c<=0)  
            return 0;

        for(int i=, i>=0; --i)
            for( int j=1; j<c; ++j ){
                memo[i] + ;
            }

        int res = bestValue( w, v, index-1, c);
        if( c >= w[index])
            res = max(res, v[index] + bestValue(w,v,index-1, c-w[index]) ); // 这里又重叠子问题了
        
        memo[index][c] = res;
        return res;
    }

Dynamic Programming:

Here Insert Picture DescriptionHere Insert Picture Description

int knapsack01(const vector<int> &w, const vector<int> &v, int C ){

        assert(v.zise() == w.size()); // 判断一下
        int n = w.size();
        if(n==0)
            return 0;

        memo = vector<vector<int>>(n, vector<int>(C+1, -1)); //memo有n行,每一行都是一个vector<int>,一共有C+1列

        for(int j=0; j<=C; ++j)
            memo[0][j] = ( j >= w[0] ? v[0] : 0 );  //j是此时背包的容量
        
        for(int i=1; i<n; ++i)
            for(int j=0; j<=C; ++j){  

                memo[i][j] = memo[i-1][j];
                if( w[i] <= j )  // 可用容量大
                    memo[i][j] = max(memo[i][j], v[i]+memo[i-1][j-w[i] ] );
            }

        return memo[n-1][C];
    }
    

01 backpack Complexity:
time complexity: O (n- C)
Complexity Space: O (n-
C)
optimize space: very small time, a large space - space optimization

Optimization 01 knapsack problem:
the state transition equation: F (i, c) = max (F (i-1, c), v (i) + F (i-1, cw (i)))
the i-th row element only dependent on the i-1 th row element. In theory, only the need to maintain two lines of elements. Thus the space complexity becomes: O (2 * C) ≈O (C)
Here Insert Picture Description
above the even-line processing, the following odd-line processing.

int knapsack01(const vector<int> &w, const vector<int> &v, int C ){

        assert(v.zise() == w.size()); // 判断一下
        int n = w.size();
        if(n==0)
            return 0;

        memo = vector<vector<int>>(2, vector<int>(C+1, -1)); //memo有n行,每一行都是一个vector<int>,一共有C+1列

        for(int j=0; j<=C; ++j)
            memo[0][j] = ( j >= w[0] ? v[0] : 0 );  //j是此时背包的容量
        
        for(int i=1; i<n; ++i)
            for(int j=0; j<=C; ++j){  

                memo[i%2][j] = memo[(i-1)%2][j];
                if( w[i] <= j )  // 可用容量大
                    memo[i%2][j] = max(memo[i%2][j], v[i]+memo[(i-1)%2][j-w[i] ] );
            }

        return memo[(n-1)%2][C];
    }
    

further optimization!
So that only one line for the C array to complete the DP
Here Insert Picture Description
for the line: Always use only the elements above and to the left, and will not touch the elements on the right!
Thus, if only one line, then look at the current value and the previous contents from right to left - thus requiring only to refresh the content - i.e. from: C = 5,4, ... 1,0
if there is a grid, loading capacity is insufficient under the current article, then this capacity before the items are not placed! We have to use the original items to put. So this algorithm also early termination of some space-time complexity can reduce the number of ~

int knapsack01(const vector<int> &w, const vector<int> &v, int C ){

        assert(v.zise() == w.size()); // 判断一下
        int n = w.size();
        if(n==0)
            return 0;

        vector<int> memo(C+1, -1); //memo有n行,每一行都是一个vector<int>,一共有C+1列

        for(int j=0; j<=C; ++j)
            memo[j] = ( j >= w[0] ? v[0] : 0 );  //j是此时背包的容量
        
        for(int i=1; i<n; ++i)
            for(int j=C; j>=w[i]; --j){   // 条件是j>w[i]
                  // 可用容量大
                memo[j] = max(memo[j], v[i] + memo[j-w[i]] );
            }

        return memo[C];
    }

01 backpack variants: the
complete knapsack problem: each item - unlimited use
(although each item can be unlimited use, but the limited capacity of the backpack, so in fact you can get to each item number is the maximum!
=== > so to convert unlimited use items knapsack problem is a little knapsack problem - use items, but there are many items are duplicates) in the list of items selected in the
optimization :( for large volume backpack when good optimization ideas) for any number, it can be used to represent a binary code, so for the same item, is not necessarily added to the list 1, but adding 124,816 such sequences, represent the same number of items taken .

Multiple backpack: each of more than one article, there num (i) th
multiple backpack is simpler

Mostly fee knapsack problem: to consider the size and weight of the item in two dimensions! (I.e. three-dimensional array) of
an article more constraints added: between articles may be mutually exclusive; may be interdependent

Published 63 original articles · won praise 13 · views 40000 +

Guess you like

Origin blog.csdn.net/changreal/article/details/102557271