分组背包(每组背包选一个物品)

每次用一个 f [ i , j ] f[i, j] f[i,j],然后去枚举一下这一组的每一个物品,分别计算选每一个的值然后每次取最大值,在此之前先赋初值为不选的值也就是 f [ i − 1 , j ] f[i - 1, j] f[i1,j],然后去比较选的最大值,但是如果是一维滚动数组的话则不需要有这一步,不赋值时就是不选的价值。

//一维
// #include <iostream>
// #include <cstring>
// #include <algorithm>

// using namespace std;

// const int N = 1005;
// int n, m;
// int f[N], v[N][N], w[N][N], s[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 j = m; j >= 0; j -- )
//         {
    
    
//             for (int k = 0; k <= s[i]; k ++ )//枚举一下这一组里的所有物品,看看加哪个多,因为去掉当前物品后的体积是没有更新过的
//             {
    
    
//                 if (j >= v[i][k]) f[j] = max(f[j], f[j - v[i][k]] + w[i][k]);
//             }
//         }
//     }
//     cout << f[m];
//     return 0;
// }

//二维
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1005;
int n, m;
int f[N][N], v[N][N], w[N][N], s[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 j = 0; j <= m; j ++ )
        {
    
    
            f[i][j] = f[i - 1][j]; //不选
            for (int k = 0; k <= s[i]; k ++ )//枚举一下这一组里的所有物品,看看加哪个多,因为去掉当前物品后的体积是没有更新过的
            {
    
    
                
                if (j >= v[i][k]) f[i][j] = max(f[i][j], f[i - 1][j - v[i][k]] + w[i][k]);
            }
        }
    }
    cout << f[n][m];
    return 0;
}

每组物品放进来枚举,用的是上一层的数据,所以不会出现串联。

Guess you like

Origin blog.csdn.net/qq_34682765/article/details/121892490