背包问题之二维费用背包问题

问题描述:对于每种物品,都具有两种不同的代价 c 1 [ i ] c_1[i] c1[i] c 2 [ i ] c_2[i] c2[i];选择该物品必须同时付出这两种代价;对于每种代价都有一个可付出的最大值(上限)。问在每个物品只能使用一次的条件下,怎么选择物品(物品保持完整)可得到最大的价值。现有数据如下:

c1 = [2,3,4,5,6,7,8];	// 代价1
cap1 = 27;	// 代价1的上限
c2 = [8,7,6,5,4,3,2];	// 代价2
cap2 = 31;	// 代价2的上限
v = [3,4,5,6,7,8,9];

解题思路:令 d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k] 表示前 i 中物品在代价1为 j,代价2为 k 的条件下装入背包的最大值。根据0-1背包问题有 d p [ i ] [ j ] [ k ] = m a x { d p [ i − 1 ] [ j ] [ k ] , d p [ i − 1 ] [ j − c 1 [ i ] ] [ k − c 2 [ i ] ] + v [ i ] } dp[i][j][k]=max\{dp[i-1][j][k],dp[i-1][j-c_1[i]][k-c_2[i]]+v[i]\} dp[i][j][k]=max{dp[i1][j][k],dp[i1][jc1[i]][kc2[i]]+v[i]}。存储结果的三位数组同样可以压缩一维,变成二维数组,即 d p [ j ] [ k ] = m a x { d p [ j ] [ k ] , d p [ j − c 1 [ i ] ] [ k − c 2 [ i ] ] + v [ i ] } dp[j][k]=max\{dp[j][k], dp[j-c_1[i]][k-c_2[i]]+v[i]\} dp[j][k]=max{dp[j][k],dp[jc1[i]][kc2[i]]+v[i]}

    public int knapsackProblem(int[] c1, int cap1, int[] c2, int cap2, int[] v) {
        int[][] dp = new int[cap1 + 1][cap2 + 1];
        for (int i = 0; i < c1.length; i++) {
            for (int j = cap1; j >= c1[i]; j--) {
                for (int k = cap2; k >= c2[i]; k--) {
                    dp[j][k] = Math.max(dp[j][k], dp[j - c1[i]][k - c2[i]] + v[i]);
                }
            }
        }
        return dp[cap1][cap2];
    }

时间复杂度为 O ( n V 1 V 2 ) O(nV_1V_2) O(nV1V2),空间复杂度为 O ( V 1 V 2 ) O(V_1V_2) O(V1V2)


上一篇:背包问题之混合背包问题
下一篇:背包问题之分组背包问题

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值