AcWing 9:分组背包问题

【题目来源】
https://www.acwing.com/problem/content/9/

【题目描述】
有 N 组物品和一个容量是 V 的背包。
每组物品有若干个,同一组内的物品最多只能选一个。
每件物品的体积是 v[i][j],价值是 w[i][j],其中 i 是组号,j 是组内编号。
求解将哪些物品装入背包,可使物品总体积不超过背包容量,且总价值最大。
输出最大价值。

【输入格式】
第一行有两个整数 N,V,用空格隔开,分别表示物品组数和背包容量。
接下来有 N 组数据:
每组数据第一行有一个整数 S[i],表示第 i 个物品组的物品数量;
每组数据接下来有 S[i] 行,每行有两个整数 v[i][j],w[i][j],用空格隔开,分别表示第 i 个物品组的第 j 个物品的体积和价值;

【输出格式】
输出一个整数,表示最大价值。

【数据范围】
0<N,V≤100
0<S[i]≤100
0<v[i][j],w[i][j]≤100

【算法分析】
因为每组最多选择一个物品,所以可以将每组都看作一个整体,这就类似于01背包问题。
令 f[i][j] 表示将前 i 组物品放入容量为 j 的背包中可以获得的最大价值,vol[i][k] 表示第 i 组第 k 个物品的体积,val[i][k] 表示第 i 组第 k 个物品的价值,cnt[i] 表示第 i 组物品的个数,则分组背包问题的状态转移方程为:
f[i][j]=f[i-1][j], j<vol[i][k]
f[i][j]=max(f[i-1][j], f[i-1][j-vol[i][k]]+val[i][k]), j>=vol[i][k]
与0-1背包问题一样,可以对分组背包问题二维实现的状态转移方程进行一维数组优化,可得:f[j]=max(f[j], f[j-vol[i][k]]+val[i][k])
其中,f[j] 表示将物品放入容量为 j 的背包中可以获得的最大价值。

【算法代码】

#include <bits/stdc++.h>
using namespace std;

const int N=105;
int vol[N][N],val[N][N],cnt[N];
int f[N];
int n,V;

int main() {
    cin>>n>>V;
    for(int i=0; i<n; i++) {
        cin>>cnt[i];
        for(int j=0; j<cnt[i]; j++) {
            cin>>vol[i][j]>>val[i][j];
        }
    }

    for(int i=0; i<n; i++) {
        for(int j=V; j>=0; j--) {
            for(int k=0; k<cnt[i]; k++) {
                if(j>=vol[i][k]) f[j]=max(f[j],f[j-vol[i][k]]+val[i][k]);
            }
        }
    }
    cout<<f[V]<<endl;

    return 0;
}


/*
in:
3 5
2
1 2
2 4
1
3 4
1
4 5

out:
8
*/



【参考文献】
https://www.acwing.com/solution/content/3483/
https://www.acwing.com/problem/content/9/
https://blog.csdn.net/whoISVip/article/details/47439451




posted @ 2026-03-21 21:44  Triwa  阅读(4)  评论(0)    收藏  举报