分组背包

先给出题目吧

通天之分组背包

题目背景

直达通天路·小 A 历险记第二篇

题目描述

\(01\) 背包问世之后,小 A 对此深感兴趣。一天,小 A 去远游,却发现他的背包不同于 \(01\) 背包,他的物品大致可分为 \(k\) 组,每组中的物品相互冲突,现在,他想知道最大的利用价值是多少。

输入格式

两个数 \(m,n\),表示一共有 \(n\) 件物品,总重量为 \(m\)

接下来 \(n\) 行,每行 \(3\) 个数 \(a_i,b_i,c_i\),表示物品的重量,利用价值,所属组数。

输出格式

一个数,最大的利用价值。

样例 #1

样例输入 #1

45 3
10 10 1
10 5 1
50 400 2

样例输出 #1

10

提示

\(0 \leq m \leq 1000\)\(1 \leq n \leq 1000\)\(1\leq k\leq 100\)\(a_i, b_i, c_i\)int 范围内。


这是多重背包的模板题
大意是:给你一个n组物品,每组选一个物品,放入背包,最大化价值并输出


首先最基本的输入数据
我们定义sum[i]表示第i组物品的数量,v[i][j]即第i组物品第j个物品的重量,w同理为价值
其次关于状态的思考

dp如何定义

我们定义dp[i][j]表示前i组物品,背包容量为j时的最大价值
根据0/1背包,我们很容易发现两者dp一样的
同理外层循环亦是一样的
for(int i=1;i<=n;i++) for(int j=0;j<=m;j++)
接下来我们考虑第三层
第三层应该是物品的循环
for(int k=1;k<=sum[i];k++)

如何进行状态转移

对于dp[i][j]我们发现,这个物品要么选要么不选,和0/1背包一样
但只能选一个
dp[i][j] = max(dp[i][j],dp[i-1][j-v[i][k]]+w[i][k]);
这是状态转移方程

解释该方程

首先dp[i][j]为不取的情况。
i不用-1是因为dp[i][j]同样是一组内其他物品所计算的最大价值(公用的),不选就是把这个dp给其他物品的最大价值。
后面那个就不用解释了吧!🙂

代码

简单,略

优化

注意到dp[i]仅与dp[i-1]有关,所以滚动数组,同0/1优化
见上一篇blog

优化代码

略(题解够多了)


完结散花 ❀ ❀ ❀ ❀ ❀

posted @ 2024-07-17 23:05  槿梶  阅读(3)  评论(0编辑  收藏  举报