动态规划-背包问题

187 阅读2分钟

问题

一个可最大载重为X的背包和Y个物品,每个物品有重量和价值两个属性。现在让你用这个背包转物品,最多能装的价值是多少?

思路

1.定义变量

背包载重:X
物品数量:Y
每个物品的重量:wt[i] (y > i > 0 )
每个物品的价值:val[i] (y > i > 0 )

2.明确dp定义

dp[i][w]定义如下,对于前i个物品,当前背包容量为w时,可以装的最大价值是dp[i][w]。
比如dp[2][4] = 6,表示选择装前2个物品,背包容量是4时,最多可装的价值是6。
我们求的是dp[N][W]?

int dp[N+1][W+1]
dp[0][...] = 0 //前0个物品不论背包多少容量不会有价值
dp[...][0] = 0 //当前背包容量为0是不会再产生价值

//逻辑
for i in [1...N]:
    for w in [1...W]:
        dp[i][w] = max(把i物品装进包,不把i物品装进包)
return dp[N][W]
如果没有把第i件物品装入背包,那么dp[i][w] = dp[i-1][w]。
否则,dp[i][w] = dp[i-1][w - wt[i]] + val[i-1]。


 for i in [1...N]:
    for w in [1...W]:
        dp[i][w] = max(dp[i-1][w - wt[i]] + val[i-1],dp[i-1][w])
return dp[N][W]

代码编写

    public static void main(String[] args) {
        //6件物品
        int N = 6;
        
        //背包容量为8
        int W = 8;
        
        //每个物品的重量
        int[] wt = new int[]{2, 1, 3, 4, 5, 1};
        
        //每个物品的价值
        int[] val = new int[]{4, 2, 3, 4, 5, 1};

        int knapsack = knapsack(W, N, wt, val);

        System.out.println("最大能装的价值是" + knapsack);

    }

    public static int knapsack(int W, int N, int[] wt, int[] val) {
        int[][] dp = new int[N + 1][W + 1];
        for (int i = 1; i <= N; i++) {
            for (int w = 1; w <= W; w++) {
                if (w - wt[i - 1] < 0) {
                    //当前背包容量无法装下
                    dp[i][w] = dp[i - 1][w];
                } else {
                    //当前物品可以装入,择优处理
                    dp[i][w] = Math.max(dp[i - 1][w - wt[i - 1]] + val[i - 1], dp[i - 1][w]);
                }
            }
        }
        return dp[N][W];
    }