背包问题

假设有abcde5个物品,重量为w1...,价值为v1...,背包的承重量为c,怎么放的价值更高数组

 

1、0/1背包问题优化

5中物品只有一件,动态规划的子问题是前i个物品放在承重量为j的背包中,状态变量:dp[i][j]spa

遍历时i在外层,j在内层,也就是每次循环先求出前i-1个物品在不一样载重量的状况下的自大价值code

而后增长一个物品,也就是前i个物品。blog

而在求前i个物品的最大价值时根据前i-1的结果:class

1.当前载重量<新增的第i件物品的重量w[i],也就是装不下变量

dp[i][j] = dp[i-1][j]循环

2.装得下遍历

dp[i][j] = max(dp[i-1][j-w[i]]+v[i],dp[i-1][j]):比较装和不装,其中若是装当前物品,那么重量占了w[i],前边i-1件物品只能使用j-w[i]的重量di

到这里时间复杂度无法优化,可是还能优化空间复杂度

咱们能够观察到,这里的i只是记录进行到前多少件物品了,其实咱们不须要前几件的结果,咱们须要的是最后的结果,因此咱们没有必要记录

i的信息。能够用一个一维数组dp[j]只记录当前信息i件物品下,不一样载重量的价值。而后每次都更新。更新到最后就是想要的

这里虽然不记录i的信息,可是仍是要保留循环,表明这是前i件的状况,i不一样的状况下,dp[j]是不一样的。

注意这里须要倒着遍历,由于dp[j]会不断更新,前边更新的结果不能影响后边
若是从前边开始,前边的dp[j]就会更新为i的状态,i-1的状态就消失了,可是后边须要这些
若是从后边开始,前边的用不到后边的结果
public void p01(int[] w,int[] v,int c){
        int[] dp = new int[c+1];
        for (int i = 0; i < w.length; i++) {
//            注意这里须要倒着遍历,由于dp[j]会不断更新,前边更新的结果不能影响后边
//            若是从前边开始,前边的dp[j]就会更新为i的状态,i-1的状态就消失了,可是后边须要这些
//            若是从后边开始,前边的用不到后边的结果
            for (int j = c; j >=w[i]; j--) {
                dp[j] = Math.max(dp[j],dp[j-w[i]]+v[i]);
            }
        }
        System.out.println(dp[c]);
    }

2.彻底背包问题

物品数量没有限制

public void pComplete(int[] w,int[] v,int c){
        int[] dp = new int[c+1];
        for (int i = 0; i < w.length; i++) {
            //这里应该从前日后遍历,01背包不能从前日后的缘由实际上是若是当前承重量能够装下多件第i件物品时
            //01问题不能装多个,因此装完后要用前一次的状态比较(前一次确定是没有装i的)
            //可是彻底背包不一样,装完后要用最新的状态比较,由于还能够继续装i
            for (int j = w[j]; j <=c; j++) {
                dp[j] = Math.max(dp[j],dp[j-w[i]]+v[i]);
            }
        }
        System.out.println(dp[c]);
    }
相关文章
相关标签/搜索