让我们先看一下题目~
【题目链接】
信息学奥赛一本通(C++版)在线评测系统 1272:【例9.16】分组背包http://ybt.ssoier.cn:8088/problem_show.php?pid=1272
【题目描述】
【输入及输出】
【输入及输出样例】
接下来就是我们的正文啦~
【题目考点】
动态规划:分组背包
【题目类型】
分组背包问题(不用想都知道)
【解题思路】
PS:该解题思路来自君义_noip的博客,博客链接:点我跳转~
分组背包问题,特点是:每组中的物品最多可以取一件
1. 状态定义
2. 状态转移方程
-
记第i组物品有m个,这m个物品的编号为i1,i2,…,im。第i物品的重量是w[i],价值是c[i]。
-
集合:在前i组物品中选择物品放入大小为j的背包的所有方案
-
分割集合:第i组物品如何放入背包
-
如果不选择第i组物品,那么在剩余i-1组中选择物品放入大小为j的背包。dp[i][j] = dp[i-1][j]
-
如果选择第i组物品中的第1个,该物品下标为i1。那么需要在剩余i-1组中选择物品放入大小为j-w[i1]的背包。dp[i][j] = dp[i-1][j-w[i1]]+c[i1]
-
如果选择第i组物品中的第2个,该物品下标为i2。那么需要在剩余i-1组中选择物品放入大小为j-w[i2]的背包。dp[i][j] = dp[i-1][j-w[i2]]+c[i2]
-
…
-
如果选择第i组物品中的第m个,该物品下标为im。那么需要在剩余i-1组中选择物品放入大小为j-w[im]的背包。dp[i][j] = dp[i-1][j-w[im]]+c[im]
-
一般地,如果选择第i组物品中的第k个,该物品下标为x。那么需要在剩余i-1组中选择物品放入大小为j-w[x]的背包。dp[i][j] = dp[i-1][j-w[x]]+c[x]。遍历第i组物品,求选择该组中每个物品后能得到的最大价值dp[i][j]。
-
以上所有情况求最大值。
3. 复杂度分析
背包容量为V,物品总数量为N,分组数量为T。
分组背包一般解法:
滚动数组优化后:
-
空间复杂度:O(V)
【代码】
#include<bits/stdc++.h>
using namespace std;
int d[210],w[15][40],c[15][40],v,n,len[15],t;
int main()
{
cin>>v>>n>>t;
for(int i=1;i<=n;i++)
{
int tw,tc,tt;
cin>>tw>>tc>>tt;
len[tt]++;
w[tt][len[tt]]=tw;
c[tt][len[tt]]=tc;
}
for(int i=1;i<=t;i++)
{
for(int j=v;j>=0;j--)
{
for(int k=1;k<=len[i];k++)
{
if(j>=w[i][k])
{
d[j]=max(d[j],d[j-w[i][k]]+c[i][k]);
}
}
}
}
cout<<d[v];
return 0;
}