”分组背包“题解

文章介绍了一个使用动态规划算法解决的背包问题变种,即有n组物品,每组内有多件不同体积和价值的物品,要求每组最多选一件,求在不超过总背包体积m的情况下,选出物品的总价值最大化。给出了相应的状态转移方程和C++代码实现。
摘要由CSDN通过智能技术生成

题目:

分析:

分组背包

n , m

n 物品组

m 背包体积

每组物品里面, 有多种物品,(每种物品只有一件)给出每组物品里, 每件物品的价值, 体积

求 从 n 组物品中选, 每组物品最 多选一件物品, 也可以不选

总体积不超过 m , 总价值最大

f[i, j] = k;

1. 集合

表示: n 组物品中选, 每组物品最 多选一件物品, 也可以不选

总体积不超过 m 的所有选法的集合

(属性, 数)存的数是这个集合中的某一个方案, 这个方案总价值最大max(价值)

2. 计算集合

f[i, j] ---> 包含的子集, 只要找 到所有子集取 Max

在这个题里面, 每个子集就是一种方案

max(1, 2, 3, 4, ...i);

f[i, j]

不选 第 i 组的物品

f[i, j] = max(f[i, j], f[i - 1, j])

选 第 i 组的物品

选第 i 组的哪一个物品

k: 第 i 组 物品中第 k 个物品

f[i, j] = max(f[i - 1, j - vik] + wik, f[i, j])

f[i,j] = max(f[i-1,j], f[i-1,j-vi1]+wi1, f[i-1,j-vi2] +wi2...f[i-1,j-vik] + wik)

f[i,j-vi1] = max(f[i-1,j-vi1],f[i-1,j-2vi1]+wi1, f[i-1,j-vi1-vi2]+wi2...f[i-1,j-vi1-vik]+wik)

3. 边界: f[0, j] = 0;

4. O(n^3)

代码:

#include <iostream>
using namespace std;

const int N = 110; 
int n, m;
int f[N][N];
int s[N], v[N][N], w[N][N];

int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i ++ )
    {
        cin >> s[i];
        for (int j = 1; j <= s[i]; j ++ )
            cin >> v[i][j] >> w[i][j]; 
    }
    for (int i = 1; i <= n; i ++ )   // 物品组 
        for (int j = 1; j <= m; j ++ )  // 体积
        {
            f[i][j] = f[i - 1][j];
            for (int k = 1; k <= s[i]; k ++ )  // 每组物品中的每个物品 
                if (v[i][k] <= j)
                    f[i][j] = max(f[i - 1][j - v[i][k]] + w[i][k], f[i][j]); 
        } 
    cout << f[n][m] << endl;
    return 0;
}

学艺不精,寥寥草草;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值