1086超市购物(分组背包)

本文介绍了一道典型的分组背包问题,并提供了详细的解决方案。通过遍历每一类商品,采用01背包的思想,实现购买预算内商品总作用值的最大化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1086: 超市购物

Time Limit: 1 Sec  Memory Limit: 128 MB SUBMIT: 122  Solved: 48 [SUBMIT] [STATUS]

Description

        上次去超市扫荡回来的东西用完了,Staginner又得跑超市一趟,出发前他列了一张购物清单,打算去买K种不同的商品,每种买一件。到了超市,Staginner发现每种商品有N个品牌,每个品牌此商品的价格为Vi,对Staginner的作用值为Wi,他会从这N个品牌里面挑一个品牌买。这时,Staginner突然想起出门时只带了M元钱,又懒得去取钱了,所以不一定能买完K种商品,只好尽可能地让买的东西对自己的总作用值ans最大。

Input

多组样例。

    第一行两个整数K,M代表Staginner想买的不同种类商品的数目和他带的钱 (0 < K <= 30, 0 < M <= 2000)
    以下输入分为K个部分,代表K种商品。
    每个部分第一行为一个数字N,代表第k种商品的N个品牌,N不大于10。之后跟着N行,每行两个数字,代表物品的价格Vi和作用值Wi。其中 0 < Vi < M。

Output

输出Case #: 最大总作用值,每两个样例之间有一个空行。

Sample Input

3 100
3
50 600
20 700
30 800		
2
30 500
40 600	
1
60 200

2 500
2
200 1000
260 1200
1
280 300

Sample Output

Case 1: 1400

Case 2: 1300

 

这是中南大学OJ上的一道典型的分组背包问题的题型。分组背包的核心其实还是01背包问题。只是做了一点点转换。

解决办法:

 for(i=0;i<K;i++)   //遍历每一类商品
   for(j=M;j>=0;j--)  //将每一个分组当做一次01背包 ,故计算顺序为M递减 
        for(u=0;u<a[i];u++) //遍历第i类中没个品牌
         if(j-v[i][u]>=0)
            f[j]=(f[j]>f[j-v[i][u]]+w[i][u] ? f[j] : f[j-v[i][u]]+w[i][u]);  //01背包的核心思想

View Code
#include<stdio.h>
#include<string.h>
int main()
{
    int K,M,i,j,u,t=0;
    int a[31],v[31][11],w[31][11],f[2001];
    while(scanf("%d %d",&K,&M)==2)
    {
        t++;
        memset(f,0,sizeof(f));
        for(i=0;i<K;i++)
        {
            scanf("%d",&a[i]);
            for(j=0;j<a[i];j++)
                scanf("%d %d",&v[i][j],&w[i][j]);
        }
        for(i=0;i<K;i++)
        {
            for(j=M;j>=0;j--)
            {
                for(u=0;u<a[i];u++)
                {
                    if(j-v[i][u]>=0)
                        f[j]=(f[j]>f[j-v[i][u]]+w[i][u] ? f[j] : f[j-v[i][u]]+w[i][u]);
                }
            }
        }
        printf("Case %d: %d\n\n",t,f[M]);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/Yz81128/archive/2012/07/21/2602594.html

### 分组背包问题的动态规划实现 分组背包问题是动态规划中的经典问题之一,通常被描述为:给定若干组物品,每组中有多个不同价值和重量的物品,从中选出一组内的某个物品放入背包中,使得总重量不超过背包容量的情况下获得的价值最大化。 以下是基于动态规划方法解决分组背包问题的具体思路以及代码实现: #### 1. 状态定义 设 `dp[j]` 表示当前状态下,在背包容量为 `j` 的情况下可以获得的最大价值。对于每一个组内的物品,我们尝试将其加入到背包中并更新状态。 #### 2. 转移方程 假设当前处理的是第 `i` 组物品,该组共有 `s[i]` 种不同的物品,其中第 `k` 个物品的重量为 `w[k]`,价值为 `v[k]`。那么状态转移方程如下: \[ dp[j] = \max(dp[j], dp[j-w[k]] + v[k]) \quad (0 \leq k < s[i], w[k] \leq j) \] 这里需要注意的是,为了防止重复计算同一个组内的物品多次选取的情况,必须按照 **逆序遍历** 背包容量 \( j \),从而确保每次只考虑前一次的状态[^2]。 #### 3. 初始化与边界条件 初始化时,令所有的 `dp[j]` 均为 0,表示当没有任何物品可选时,无论背包容量如何,能够获取的最大价值都为零。 #### 4. 时间复杂度分析 时间复杂度主要由三部分组成:外层循环遍历所有组数 \( N \),中间循环遍历每个组内部的不同物品数量 \( S_i \),内层循环遍历背包容量 \( C \)。因此总体的时间复杂度为 \( O(N \cdot C \cdot \text{avg}(S)) \)[^4],其中 \( \text{avg}(S) \) 是平均每组的物品数目。 下面是具体的 Python 实现代码: ```python def group_knapsack(groups, capacity): """ :param groups: List[List[Tuple[int,int]]] 每组是一个列表,包含元组(重量, 价值) :param capacity: int 背包最大容量 :return: int 最大价值 """ n_groups = len(groups) dp = [0] * (capacity + 1) for g in range(n_groups): # 遍历每一组 for j in range(capacity, -1, -1): # 倒序遍历背包容量 for item_weight, item_value in groups[g]: # 遍历当前组的所有物品 if j >= item_weight: dp[j] = max(dp[j], dp[j-item_weight] + item_value) return dp[capacity] # 测试数据 groups = [ [(2, 3), (3, 4)], # 第一组有两个物品,分别权重为2价值为3,权重为3价值为4 [(4, 5), (5, 6)] # 第二组也有两个物品 ] capacity = 7 result = group_knapsack(groups, capacity) print(f"Maximum value achievable with capacity {capacity} is {result}") ``` 上述代码实现了分组背包问题的核心逻辑,并通过测试样例验证了其正确性。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值