多重背包

这篇博客探讨了两种背包问题:798. 背包问题VII 和 799. 背包问题VIII。在798中,讨论了如何用有限的金钱购买最大重量的大米;在799中,涉及如何用不同价值和数量的硬币组合出1到n的所有可能值。文章通过样例展示了问题的解决策略和结果。
摘要由CSDN通过智能技术生成

798. 背包问题VII

中文English
假设你身上有 n 元,超市里有多种大米可以选择,每种大米都是袋装的,必须整袋购买,给出每种大米的重量,价格以及数量,求最多能买多少公斤的大米

样例
样例 1:

输入: n = 8, prices = [3,2], weights = [300,160], amounts = [1,6]
输出: 640
解释: 全买价格为2的米。
样例 2:

输入: n = 8, prices = [2,4], weight = [100,100], amounts = [4,2 ]
输出: 400
解释: 全买价格为2的米

class Solution:
    """
    @param m: the money of you
    @param prices: the price of rice[i]
    @param weight: the weight of rice[i]
    @param amounts: the amount of rice[i]
    @return: the maximum weight
    """
    def backPackVII(self, m, prices, weight, amounts):
        # write your code here
        '''
        本题a[i][j]表示以j元能买到的前i件物品的最大重量
        a[i][j] = max(a[i][j], a[i-1][j-k*prices[i]] + k*weight[i])
        0=<k<=amount[i], and k <= j//prices[i] 
        '''
        n = len(prices)
        
        a = [[0 for _ in range(m+1)] for _ in range(n+1)]
        
        prices = [0] + prices
        weight = [0] + weight
        amounts = [0] + amounts
        
        for i in range(1, n+1):
            for j in range(0, m+1):
                s = j // prices[i] #j元最多能买多少
                for k in range(amounts[i]+1):
                    '''注意这里max,a[i][j]而不是a[i-1][j],是因为每次都需要和上一次的最大值比,而最
                    大值保存在a[i][j]中
                    '''
                    if j >= k * prices[i]:
                        #如果k大于最多能买的数量,则不能放入
                        a[i][j] = max(a[i][j], a[i-1][j-k*prices[i]] + k*weight[i])
        return a[n][m]


799. 背包问题VIII

给一些不同价值和数量的硬币。找出这些硬币可以组合在1 ~ n范围内的值的数量

样例
样例 1:
输入:
n = 5
value = [1,4]
amount = [2,1]
输出: 4

解释:
可以组合出1,2,4,5

样例 2:
输入:
n = 10
value = [1,2,4]
amount = [2,1,1]
输出: 8
解释:
可以组合出1-8所有数字。

public class Solution {
    /**
     * @param n: the value from 1 - n
     * @param value: the value of coins
     * @param amount: the number of coins
     * @return: how many different value
     *         a[i][j]表示前i个物品是否能组成价值j
        a[i][j] = a[i][j] or a[i-1][j-k*value[i]]
        注意初始化a[0...n][0]=true
     */
    public int backPackVIII(int m, int[] value, int[] amount) {
        // write your code here
        int n = value.length;

        boolean[][] a = new boolean[n+1][m+1];
        
        for (int i = 0; i < n+1; i++){
            for (int j = 0; j < m+1; j++){
                a[i][j] = false;
            }
        }
        //前i个物品能够组成价值0,都选0个,j=0的时候设置为1
        for (int i = 0; i < n+1;i++ ){
            a[i][0] = true;
        } 
        
        for (int i = 1; i < n+1 ;i++ ){
            for (int j = 0; j < m+1;j++ ){
                for (int k = 0; k < amount[i-1]+1;k++ ){
                    
                    if (j >= k * value[i-1]){
                     //只要有一个能组成就可以了,所以是or
                        a[i][j] = a[i][j] | a[i-1][j - k * value[i-1]];
                        
                        if(a[i][j]){
                            break;
                        }
                    }
                } 
            } 
        }
        
        int cnt = 0;
        for (int i = 1; i < m+1 ; i++){
            if (a[n][i]){
                cnt += 1;
            }
        }
        return cnt;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值