二维费用的背包问题,小白也可以看懂,哦耶~

问题描述:

背包的容量是V,能承受的最大的重量是M
有N个物品,v, m, w数组中分别存放着每个物品的体积,重量,价值
求解将哪些物品装入背包,可使物品总体积不超过背包容量,物品的总重不超过背包能承受的最大重量,且总价值最大

思路分析:
方案一:

dp数组的含义是:背包在一定的体积和重量下,可以获得的最大价值
假设现在要装第i件物品,那么dp[i - 1]储存的就是装这件物品之前的所有物品可以获得的最大价值,通过装第i件物品,实现dp[i]的更新,更新为包括第i件物品可以获得的最大价值。所以下面的代码对应的是dp[i - 1]
在体积为j,重量为k的条件下,装入第i件物品,体积得腾出v[i],重量也得腾出m[i],这样才可以装下第i件物品,如果可以装下,那么背包的价值在 dp[i - 1][j - v[i]][k - m[i]] 的条件下增加了w[i],和之前的进行比较,选出最优解

dp[i][j][k] = Math.max(dp[i - 1][j][k], dp[i - 1][j - v[i]][k - m[i]] + w[i]);
优化版:

和之前的一样,咱们需要的数据只有dp[i - 1],如果从后往前遍历就不会破坏原来的dp[i - 1]数据

dp[j][k] = Math.max(dp[j][k], dp[j - v[i]][k - m[i]] + w[i]);
代码:
public class Main {

    int N;   //有N个物品
    int V;   //背包的容量为V
    int M;   //背包能承受的最大重量
    int[] v; //每个物品的体积
    int[] m; //每个物品的重量
    int[] w; //每个物品的价值
    
    public int two_dimension1(){
        int[][][] dp = new int[N + 1][V + 1][M + 1];
        
        for(int i = 1; i <= N; i++){
            for(int j = 1; j <= V; j++){
                for(int k = 1; k <= M; k++){
                    if(j < v[i] || k < m[i]){
                        dp[i][j][k] = dp[i - 1][j][k];
                    }
                    else{
                        dp[i][j][k] = Math.max(dp[i - 1][j][k], dp[i - 1][j - v[i]][k - m[i]] + w[i]);
                    }
                }
            }
        }
        
        return dp[N][V][M];
    }
	
	//优化
    public int two_dimension2(){
        int[][] dp = new int[V + 1][M + 1];
        for(int i = 1; i <= N; i++){
            for(int j = V; j >= 1; j--){
                for(int k = M; k >= 1; k--){
                    if(j < v[i] || k < m[i]){
                        dp[j][k] = dp[j][k];
                    }
                    else{
                        dp[j][k] = Math.max(dp[j][k], dp[j - v[i]][k - m[i]] + w[i]);
                    }
                }
            }
        }
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值