📜  针对0-1背包问题的空间优化DP解决方案

📅  最后修改于: 2021-04-29 12:11:21             🧑  作者: Mango

给定n个物料的权重和值,将这些物料放在容量为W的背包中,以在背包中获得最大的总价值。换句话说,给定两个整数数组val [0..n-1]和wt [0..n-1],它们分别表示与n个项目相关联的值和权重。还要给定代表背包容量的整数W,找出val []的最大值子集,使该子集的权重之和小于或等于W。不要选择它(0-1个属性)。
这里W <= 2000000和n <= 500
例子:

Input : W = 10, n = 3
        val[] = {7, 8, 4}
        wt[] = {3, 8, 6}
Output: 11
We get maximum value by picking items of 3 KG and 6 KG.

我们在这里讨论了基于动态编程的解决方案。在先前的解决方案中,我们使用* W矩阵。我们可以减少所用的额外空间。优化背后的想法是,要计算mat [i] [j],我们只需要上一行的解决方案即可。在0-1背包问题中,如果我们当前在mat [i] [j]上,并且包含第ith个元素,那么我们将j-wt [i]步移回上一行,如果排除当前元素,则在第j列移动前一行。因此,在这里我们可以观察到一次我们仅处理2个连续的行。
在下面的解决方案中,我们创建一个大小为2 * W的矩阵。如果n为奇数,则最终答案将在mat [0] [W]处;如果n为偶数,则最终答案将在mat [1] [W]处,因为索引从0开始。

C++
// C++ program of a space optimized DP solution for
// 0-1 knapsack problem.
#include
using namespace std;
 
// val[] is for storing maximum profit for each weight
// wt[] is for storing weights
// n number of item
// W maximum capacity of bag
// mat[2][W+1] to store final result
int KnapSack(int val[], int wt[], int n, int W)
{
    // matrix to store final result
    int mat[2][W+1];
    memset(mat, 0, sizeof(mat));
 
    // iterate through all items
    int i = 0;
    while (i < n) // one by one traverse each element
    {
        int j = 0; // traverse all weights j <= W
 
        // if i is odd that mean till now we have odd
        // number of elements so we store result in 1th
        // indexed row
        if (i%2!=0)
        {
            while (++j <= W) // check for each value
            {
                if (wt[i] <= j) // include element
                    mat[1][j] = max(val[i] + mat[0][j-wt[i]],
                                    mat[0][j] );
                else           // exclude element
                    mat[1][j] = mat[0][j];
            }
 
        }
 
        // if i is even that mean till now we have even number
        // of elements so we store result in 0th indexed row
        else
        {
            while(++j <= W)
            {
                if (wt[i] <= j)
                    mat[0][j] = max(val[i] + mat[1][j-wt[i]],
                                     mat[1][j]);
                else
                    mat[0][j] = mat[1][j];
            }
        }
        i++;
    }
 
    // Return mat[0][W] if n is odd, else mat[1][W]
    return (n%2 != 0)? mat[0][W] : mat[1][W];
}
 
// Driver program to test the cases
int main()
{
    int val[] = {7, 8, 4}, wt[] = {3, 8, 6}, W = 10, n = 3;
    cout << KnapSack(val, wt, n, W) << endl;
    return 0;
}


Java
// Java program of a space optimized DP solution for
// 0-1 knapsack problem.
class GFG
{
     
    // val[] is for storing maximum
    // profit for each weight
    // wt[] is for storing weights
    // n number of item
    // W maximum capacity of bag
    // mat[2][W+1] to store final result
    static int KnapSack(int val[], int wt[],
                            int n, int W)
    {
        // matrix to store final result
        int mat[][] = new int[2][W + 1];
 
        // iterate through all items
        int i = 0;
        while (i < n) // one by one traverse each element
        {
            int j = 0; // traverse all weights j <= W
 
            // if i is odd that mean till now we have odd
            // number of elements so we store result in 1th
            // indexed row
            if (i % 2 != 0)
            {
                while (++j <= W) // check for each value
                {
                    if (wt[i] <= j) // include element
                    {
                        mat[1][j] = Math.max(val[i] + mat[0][j - wt[i]],
                                                      mat[0][j]);
                    } else // exclude element
                    {
                        mat[1][j] = mat[0][j];
                    }
                }
 
            }
             
            // if i is even that means till now
            // we have even number of elements
            // so we store result in 0th indexed row
            else
            {
                while (++j <= W)
                {
                    if (wt[i] <= j)
                    {
                        mat[0][j] = Math.max(val[i] + mat[1][j - wt[i]],
                                                      mat[1][j]);
                    } else
                    {
                        mat[0][j] = mat[1][j];
                    }
                }
            }
            i++;
        }
 
        // Return mat[0][W] if n is odd, else mat[1][W]
        return (n % 2 != 0) ? mat[0][W] : mat[1][W];
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        int val[] = {7, 8, 4},
            wt[] = {3, 8, 6},
            W = 10, n = 3;
        System.out.println(KnapSack(val, wt, n, W));
    }
}
 
// This code is contributed by PrinciRaj1992


Python3
# Python program of a space
# optimized DP solution for
# 0-1 knapsack problem.
 
# val[] is for storing maximum
# profit for each weight
# wt[] is for storing weights
# n number of item
# W maximum capacity of bag
# mat[2][W+1] to store final result
 
def KnapSack(val, wt, n, W):
     
    # matrix to store final result
    mat = [[0 for i in range(W + 1)]
              for i in range(2)]
    # iterate through all items
    i = 0
    while i < n: # one by one traverse
                 # each element
        j = 0 # traverse all weights j <= W
         
        # if i is odd that mean till
        # now we have odd number of
        # elements so we store result 
        # in 1th indexed row
        if i % 2 == 0:
            while j < W: # check for each value
                j += 1
                if wt[i] <= j: # include element
                    mat[1][j] = max(val[i] + mat[0][j -
                                     wt[i]], mat[0][j])
                else: # exclude element
                    mat[1][j] = mat[0][j]
                     
        # if i is even that mean till
        # now we have even number
        # of elements so we store
        # result in 0th indexed row
        else:
            while j < W:
                j += 1
                if wt[i] <= j:
                    mat[0][j] = max(val[i] + mat[1][j -
                                     wt[i]], mat[1][j])
                else:
                    mat[0][j] = mat[1][j]
        i += 1
    # Return mat[0][W] if n is
    # odd, else mat[1][W]
    if n % 2 == 0:
        return mat[0][W]
    else:
        return mat[1][W]
 
# Driver code
val = [7, 8, 4]
wt = [3, 8, 6]
W = 10
n = 3
print(KnapSack(val, wt, n, W))
 
# This code is contributed
# by sahilshelangia


C#
// C# program of a space optimized DP solution for
// 0-1 knapsack problem.
using System;
     
class GFG
{
     
    // val[] is for storing maximum
    // profit for each weight
    // wt[] is for storing weights
    // n number of item
    // W maximum capacity of bag
    // mat[2,W+1] to store final result
    static int KnapSack(int []val, int []wt,
                            int n, int W)
    {
        // matrix to store final result
        int [,]mat = new int[2, W + 1];
 
        // iterate through all items
        int i = 0;
        while (i < n) // one by one traverse each element
        {
            int j = 0; // traverse all weights j <= W
 
            // if i is odd that mean till now we have odd
            // number of elements so we store result in 1th
            // indexed row
            if (i % 2 != 0)
            {
                while (++j <= W) // check for each value
                {
                    if (wt[i] <= j) // include element
                    {
                        mat[1, j] = Math.Max(val[i] + mat[0, j - wt[i]],
                                                      mat[0, j]);
                    } else // exclude element
                    {
                        mat[1,j] = mat[0,j];
                    }
                }
 
            }
             
            // if i is even that means till now
            // we have even number of elements
            // so we store result in 0th indexed row
            else
            {
                while (++j <= W)
                {
                    if (wt[i] <= j)
                    {
                        mat[0, j] = Math.Max(val[i] + mat[1, j - wt[i]],
                                                      mat[1, j]);
                    }
                    else
                    {
                        mat[0, j] = mat[1, j];
                    }
                }
            }
            i++;
        }
 
        // Return mat[0,W] if n is odd, else mat[1,W]
        return (n % 2 != 0) ? mat[0, W] : mat[1, W];
    }
 
    // Driver Code
    public static void Main(String[] args)
    {
        int []val = {7, 8, 4};
        int []wt = {3, 8, 6};
        int W = 10, n = 3;
        Console.WriteLine(KnapSack(val, wt, n, W));
    }
}
 
// This code is contributed by 29AjayKumar


PHP


Javascript


C++
// C++ program of a space optimized DP solution for
// 0-1 knapsack problem.
#include
using namespace std;
 
// val[] is for storing maximum profit for each weight
// wt[] is for storing weights
// n number of item
// W maximum capacity of bag
// dp[W+1] to store final result
int KnapSack(int val[], int wt[], int n, int W)
{
    // array to store final result
    //dp[i] stores the profit with KnapSack capacity "i"
    int dp[W+1];
     
    //initially profit with 0 to W KnapSack capacity is 0
    memset(dp, 0, sizeof(dp));
 
    // iterate through all items
    for(int i=0; i < n; i++)
        //traverse dp array from right to left
        for(int j=W; j>=wt[i]; j--)
            dp[j] = max(dp[j] , val[i] + dp[j-wt[i]]);
    /*above line finds out maximum of  dp[j](excluding ith element value)
      and val[i] + dp[j-wt[i]] (including ith element value and the
      profit with "KnapSack capacity - ith element weight") */   
    return dp[W];
}
 
// Driver program to test the cases
int main()
{
    int val[] = {7, 8, 4}, wt[] = {3, 8, 6}, W = 10, n = 3;
    cout << KnapSack(val, wt, n, W) << endl;
    return 0;
}
 
// This code is contributed by Gaurav Mamgain


Java
// Java program of a space optimized DP solution for
// 0-1 knapsack problem.
import java.util.Arrays;
 
class GFG
{
 
 
// val[] is for storing maximum profit for each weight
// wt[] is for storing weights
// n number of item
// W maximum capacity of bag
// dp[W+1] to store final result
static int KnapSack(int val[], int wt[], int n, int W)
{
    // array to store final result
    //dp[i] stores the profit with KnapSack capacity "i"
    int []dp = new int[W+1];
     
    //initially profit with 0 to W KnapSack capacity is 0
    Arrays.fill(dp, 0);
 
    // iterate through all items
    for(int i=0; i < n; i++)
     
        //traverse dp array from right to left
        for(int j = W; j >= wt[i]; j--)
            dp[j] = Math.max(dp[j] , val[i] + dp[j - wt[i]]);
             
    /*above line finds out maximum of dp[j](excluding ith element value)
    and val[i] + dp[j-wt[i]] (including ith element value and the
    profit with "KnapSack capacity - ith element weight") */
    return dp[W];
}
 
// Driver code
public static void main(String[] args)
{
    int val[] = {7, 8, 4}, wt[] = {3, 8, 6}, W = 10, n = 3;
    System.out.println(KnapSack(val, wt, n, W));
}
}
 
// This code is contributed by Princi Singh


Python3
# Python program of a space optimized DP solution for
# 0-1 knapsack problem.
 
# val[] is for storing maximum profit for each weight
# wt[] is for storing weights
# n number of item
# W maximum capacity of bag
# dp[W+1] to store final result
def KnapSack(val, wt, n, W):
     
    # array to store final result
    # dp[i] stores the profit with KnapSack capacity "i"
    dp = [0]*(W+1);
 
    # iterate through all items
    for i in range(n):
         
        #traverse dp array from right to left
        for j in range(W,wt[i],-1):
            dp[j] = max(dp[j] , val[i] + dp[j-wt[i]]);
             
    '''above line finds out maximum of dp[j](excluding ith element value)
    and val[i] + dp[j-wt[i]] (including ith element value and the
    profit with "KnapSack capacity - ith element weight") *'''
    return dp[W];
 
 
# Driver program to test the cases
val = [7, 8, 4];
wt = [3, 8, 6];
W = 10; n = 3;
print(KnapSack(val, wt, n, W));
 
# This code is contributed by Princi Singh


C#
// C# program of a space optimized DP solution for
// 0-1 knapsack problem.
using System;
 
class GFG
{
 
// val[] is for storing maximum profit for each weight
// wt[] is for storing weights
// n number of item
// W maximum capacity of bag
// dp[W+1] to store final result
static int KnapSack(int []val, int []wt, int n, int W)
{
    // array to store final result
    //dp[i] stores the profit with KnapSack capacity "i"
    int []dp = new int[W + 1];
     
    //initially profit with 0 to W KnapSack capacity is 0
    for(int i = 0; i < W + 1; i++)
        dp[i] = 0;
 
    // iterate through all items
    for(int i = 0; i < n; i++)
     
        //traverse dp array from right to left
        for(int j = W; j >= wt[i]; j--)
            dp[j] = Math.Max(dp[j] , val[i] + dp[j - wt[i]]);
             
    /*above line finds out maximum of dp[j](excluding ith element value)
    and val[i] + dp[j-wt[i]] (including ith element value and the
    profit with "KnapSack capacity - ith element weight") */
    return dp[W];
}
 
// Driver code
public static void Main(String[] args)
{
    int []val = {7, 8, 4};
    int []wt = {3, 8, 6};
    int W = 10, n = 3;
    Console.WriteLine(KnapSack(val, wt, n, W));
}
}
 
// This code is contributed by Rajput-Ji


Javascript


输出:

11

时间复杂度: O(n * W)
辅助空间: O(W)
这是Gaurav Mamgain提供的优化代码

C++

// C++ program of a space optimized DP solution for
// 0-1 knapsack problem.
#include
using namespace std;
 
// val[] is for storing maximum profit for each weight
// wt[] is for storing weights
// n number of item
// W maximum capacity of bag
// dp[W+1] to store final result
int KnapSack(int val[], int wt[], int n, int W)
{
    // array to store final result
    //dp[i] stores the profit with KnapSack capacity "i"
    int dp[W+1];
     
    //initially profit with 0 to W KnapSack capacity is 0
    memset(dp, 0, sizeof(dp));
 
    // iterate through all items
    for(int i=0; i < n; i++)
        //traverse dp array from right to left
        for(int j=W; j>=wt[i]; j--)
            dp[j] = max(dp[j] , val[i] + dp[j-wt[i]]);
    /*above line finds out maximum of  dp[j](excluding ith element value)
      and val[i] + dp[j-wt[i]] (including ith element value and the
      profit with "KnapSack capacity - ith element weight") */   
    return dp[W];
}
 
// Driver program to test the cases
int main()
{
    int val[] = {7, 8, 4}, wt[] = {3, 8, 6}, W = 10, n = 3;
    cout << KnapSack(val, wt, n, W) << endl;
    return 0;
}
 
// This code is contributed by Gaurav Mamgain

Java

// Java program of a space optimized DP solution for
// 0-1 knapsack problem.
import java.util.Arrays;
 
class GFG
{
 
 
// val[] is for storing maximum profit for each weight
// wt[] is for storing weights
// n number of item
// W maximum capacity of bag
// dp[W+1] to store final result
static int KnapSack(int val[], int wt[], int n, int W)
{
    // array to store final result
    //dp[i] stores the profit with KnapSack capacity "i"
    int []dp = new int[W+1];
     
    //initially profit with 0 to W KnapSack capacity is 0
    Arrays.fill(dp, 0);
 
    // iterate through all items
    for(int i=0; i < n; i++)
     
        //traverse dp array from right to left
        for(int j = W; j >= wt[i]; j--)
            dp[j] = Math.max(dp[j] , val[i] + dp[j - wt[i]]);
             
    /*above line finds out maximum of dp[j](excluding ith element value)
    and val[i] + dp[j-wt[i]] (including ith element value and the
    profit with "KnapSack capacity - ith element weight") */
    return dp[W];
}
 
// Driver code
public static void main(String[] args)
{
    int val[] = {7, 8, 4}, wt[] = {3, 8, 6}, W = 10, n = 3;
    System.out.println(KnapSack(val, wt, n, W));
}
}
 
// This code is contributed by Princi Singh

Python3

# Python program of a space optimized DP solution for
# 0-1 knapsack problem.
 
# val[] is for storing maximum profit for each weight
# wt[] is for storing weights
# n number of item
# W maximum capacity of bag
# dp[W+1] to store final result
def KnapSack(val, wt, n, W):
     
    # array to store final result
    # dp[i] stores the profit with KnapSack capacity "i"
    dp = [0]*(W+1);
 
    # iterate through all items
    for i in range(n):
         
        #traverse dp array from right to left
        for j in range(W,wt[i],-1):
            dp[j] = max(dp[j] , val[i] + dp[j-wt[i]]);
             
    '''above line finds out maximum of dp[j](excluding ith element value)
    and val[i] + dp[j-wt[i]] (including ith element value and the
    profit with "KnapSack capacity - ith element weight") *'''
    return dp[W];
 
 
# Driver program to test the cases
val = [7, 8, 4];
wt = [3, 8, 6];
W = 10; n = 3;
print(KnapSack(val, wt, n, W));
 
# This code is contributed by Princi Singh

C#

// C# program of a space optimized DP solution for
// 0-1 knapsack problem.
using System;
 
class GFG
{
 
// val[] is for storing maximum profit for each weight
// wt[] is for storing weights
// n number of item
// W maximum capacity of bag
// dp[W+1] to store final result
static int KnapSack(int []val, int []wt, int n, int W)
{
    // array to store final result
    //dp[i] stores the profit with KnapSack capacity "i"
    int []dp = new int[W + 1];
     
    //initially profit with 0 to W KnapSack capacity is 0
    for(int i = 0; i < W + 1; i++)
        dp[i] = 0;
 
    // iterate through all items
    for(int i = 0; i < n; i++)
     
        //traverse dp array from right to left
        for(int j = W; j >= wt[i]; j--)
            dp[j] = Math.Max(dp[j] , val[i] + dp[j - wt[i]]);
             
    /*above line finds out maximum of dp[j](excluding ith element value)
    and val[i] + dp[j-wt[i]] (including ith element value and the
    profit with "KnapSack capacity - ith element weight") */
    return dp[W];
}
 
// Driver code
public static void Main(String[] args)
{
    int []val = {7, 8, 4};
    int []wt = {3, 8, 6};
    int W = 10, n = 3;
    Console.WriteLine(KnapSack(val, wt, n, W));
}
}
 
// This code is contributed by Rajput-Ji

Java脚本


输出:

11