0
点赞
收藏
分享

微信扫一扫

AcWing 9. 分组背包问题

JWvFczgRNg.jpg

题目

思路

状态表示 -- 集合:从前i组中选,体积不超过j的最大值的集合。
         -- 属性:Max
状态计算:
    当遍历到第i组时,存在不取、取物品1、取物品2、...、取物品k多种情况。
    0: f[i][j] = f[i - 1][j]
    1: f[i][j] = f[i - 1][j - v1] + w1
    ...
    k: f[i][j] = f[i - 1][j - vk] + wk
以上为朴素算法基本思路
与01背包类似,分组背包可以优化到1维,相同思路。

代码

1. 朴素算法

#include <iostream>

using namespace std;

const int N = 110;

int f[N][N];
int v[N][N], w[N][N], s[N];

int main()
{
    int n, m;
    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 = 0; j <= m; j ++ )  // 遍历体积
        {
            f[i][j] = max(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][j], f[i - 1][j - v[i][k]] + w[i][k]);
            }
        }
            
            
    cout << f[n][m] << endl;
    
    return 0;
}

2. 优化至1维

#include <iostream>

using namespace std;

const int N = 110;

int f[N];
int v[N][N], w[N][N], s[N];

int main()
{
    int n, m;
    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 = m; j >= 0; j -- )  // 遍历体积
            for (int k = 1; k <= s[i]; k ++ )  // 取
            {
                if (v[i][k] <= j)
                    f[j] = max(f[j], f[j - v[i][k]] + w[i][k]);
            }
            
    cout << f[m] << endl;
    
    return 0;
}
举报

相关推荐

0 条评论