题解 | #0-1背包和完全背包#

【模板】完全背包

http://www.nowcoder.com/practice/237ae40ea1e84d8980c1d5666d1c53bc

一、0-1背包

第一类问题:最大价值

  1. 确定状态
    容量+剩余物品数量
  2. 确定选择
    针对一个物品放入背包或者不放入背包两种选择
  3. 确定dp含义
    dp[i][j]表示针对前i个物品,在容量为j的限制下,所能存放的最大价值
  4. 确定base case
    当物品数量为0或者背包体积为0时,最大价值为0,即dp[0][x]=0,dp[x][0]=0
  5. 确定状态转移方程
dp[i][j]=max{dp[i-1][j],w[i]+dp[i-1][j-v[i]]]}
  1. Java实现
public static int max(int n,int V,int[][] vw){
        int[][] dp = new int[n+1][V+1];
        for(int i=0;i<n+1;i++){
            dp[i][0] = 0;
        }
        for(int j=1;j<V+1;j++){
            dp[0][j] = 0;
        }
        for(int i=1;i<n+1;i++){
            for(int j=1;j<V+1;j++){
                if(vw[i-1][0]>j){
                    dp[i][j] = dp[i-1][j];
                }else{
                    dp[i][j] = Math.max(dp[i-1][j],vw[i-1][1]+dp[i-1][j-vw[i-1][0]]);
                }
            }
        }
        return dp[n][V];
    }

第二类问题:刚好装满时最大价值

  1. 确定状态
    容量+剩余物品数量
  2. 确定选择
    针对一个物品放入背包或者不放入背包两种选择
  3. 确定dp含义
    dp[i][j]表示针对前i个物品,在容量为j的限制下,所能存放的最大价值
  4. 确定base case
    当物品数量为0时,若体积大于0,则无法装满,用Integer.MIN_VALUE来表示,当体积为0时,存放最大价值为0,则dp[0][1...x]=Integer.MIN_VALUE,dp[0...x][0]=0
  5. 确定状态转移方程
dp[i][j]=max{dp[i-1][j],w[i]+dp[i-1][j-v[i]]]}
  1. Java实现
public static int maxWhenFull(int n,int V,int[][] vw){
      int[][] dp = new int[n+1][V+1];
        for(int i=0;i<n+1;i++){
            dp[i][0] = 0;
        }
        for(int j=1;j<V+1;j++){
            dp[0][j] = Integer.MIN_VALUE;
        }
        for(int i=1;i<n+1;i++){
            for(int j=1;j<V+1;j++){
                if(vw[i-1][0]>j){
                    dp[i][j] = dp[i-1][j];
                }else{
                    dp[i][j] = Math.max(dp[i-1][j],vw[i-1][1]+dp[i-1][j-vw[i-1][0]]);
                }
            }
        }
        return dp[n][V]<0?0:dp[n][V];
    }
    

二、完全背包

第一类问题:最大价值

  1. 确定状态
    容量+剩余物品数量
  2. 确定选择
    针对一个物品有k种选择,k=0,1,2....,同时满足k*v[i]<j,就是说k不能无限增大,要考虑背包的容量
  3. 确定dp含义
    dp[i][j]表示针对前i个物品,在容量为j的限制下,所能存放的最大价值
  4. 确定base case
    当物品数量为0或者背包体积为0时,最大价值为0,即dp[0][x]=0,dp[x][0]=0
  5. 确定状态转移方程
dp[i][j]=max{k*w[i]+dp[i-1][j-k*v[i]]]}
  1. Java实现
    public static int getMax(int n,int V,int[][] vw){
        int[][] dp = new int[n+1][V+1];
        for(int i=0;i<n+1;i++){
            dp[i][0]=0;
        }
        for(int j=0;j<V+1;j++){
            dp[0][j]=0;
        }
        for(int i=1;i<n+1;i++){
            for(int j=1;j<V+1;j++){
                int max = dp[i-1][j];
                for(int k=0;k*vw[i-1][0]<=j;k++){
                    max = Math.max(max,k*vw[i-1][1]+dp[i-1][j-k*vw[i-1][0]]);
                }
                dp[i][j] = max;
            }
        }
        return dp[n][V];
    }

第二类问题:刚好装满时最大价值

  1. 确定状态
    容量+剩余物品数量
  2. 确定选择
    针对一个物品有k种选择,k=0,1,2....,同时满足k*v[i]<j,就是说k不能无限增大,要考虑背包的容量
  3. 确定dp含义
    dp[i][j]表示针对前i个物品,在容量为j的限制下,所能存放的最大价值
  4. 确定base case
    当物品数量为0时,若体积大于0,则无法装满,用Integer.MIN_VALUE来表示,当体积为0时,存放最大价值为0,则dp[0][1...x]=Integer.MIN_VALUE,dp[0...x][0]=0
  5. 确定状态转移方程
dp[i][j]=max{k*w[i]+dp[i-1][j-k*v[i]]]}
  1. Java实现
    public static int getMaxWhenFull(int n,int V,int[][] vw){
        int[][] dp = new int[n+1][V+1];
        for(int i=0;i<n+1;i++){
            dp[i][0]=0;
        }
        for(int j=1;j<V+1;j++){
            dp[0][j]=Integer.MIN_VALUE;
        }
        for(int i=1;i<n+1;i++){
            for(int j=1;j<V+1;j++){
                int max = dp[i-1][j];
                for(int k=0;k*vw[i-1][0]<=j;k++){
                    max = Math.max(max,k*vw[i-1][1]+dp[i-1][j-k*vw[i-1][0]]);
                }
                dp[i][j] = max;
            }
        }
        return dp[n][V]>0?dp[n][V]:0;
    }

三、总结

0-1背包是完全背包的特殊情况!
刚好装满时最大价值与直接最大价值的区别在于base case初始化的不同!

全部评论
第二问不对吧
点赞 回复 分享
发布于 2023-10-21 10:01 辽宁
老哥写的真是精辟!
点赞 回复 分享
发布于 2022-09-15 21:07 北京

相关推荐

深夜书店vv:腾讯是这样的,去年很多走廊都加桌子当工区
点赞 评论 收藏
分享
牛客92804383...:在他心里你已经是他的员工了
点赞 评论 收藏
分享
找个工作&nbsp;学历是要卡的&nbsp;要求是高的&nbsp;技能不足是真的&nbsp;实习经验是0的&nbsp;简历无处可写是事实的&nbsp;钱不好赚是真的&nbsp;想躺平又不敢躺&nbsp;也不甘心躺&nbsp;怕自己的灵感和才华被掩埋甚至从未被自己发现&nbsp;又质疑自己是否真正有才华
码农索隆:你现在啊,你心里都明白咋回事,但是你没办法改变现状,一想到未来,你又没有信心狠下心来在当下努力。 得走出这种状态,不能一直困在那里面,哪不行就去提升哪,你一动不动那指定改变不了未来,动起来,积少成多才能越来越好
点赞 评论 收藏
分享
评论
23
4
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务