跳转到内容
GYX / Blog

完全背包问题

大体上与01背包问题类似,区别在于:完全背包问题没有对于物品数量的限制

  • v[   ]v[ \ \ \ ]记录体积,w[   ]w[ \ \ \ ] 记录价值,dp[   ][   ]dp[ \ \ \ ][ \ \ \ ] 记录状态 (朴素做法用二维)
  • 状态计算\textbf{\textcolor{green}{状态计算}}: 将 dp[   ][   ]dp[\ \ \ ][\ \ \ ] 分为包含第 ii 个数和不包含第 ii 个数。

优化方法也是滚动数组。

代码区别点:完全背包问题对于 jj 是正序遍历。

正序遍历原因:

  • 充分性:由于完全背包问题没有数量限制,因此不存在01背包中出现的一物不可多用\textbf{\textcolor{Cyan}{一物不可多用}}的限制
  • 必要性:由于没有数量限制,所以会出现一种物品需要多次使用\textbf{\textcolor{Cyan}{一种物品需要多次使用}}的情况,因此这时候 dp[ i ][ j ]dp[\ i \ ][\ j \ ] 的值不来源于 dp[ i−1 ][   ]dp[\ i-1 \ ][\ \ \ ] ,即不来自于上一层,而是来源于同一层中的前 ii 个值,因此优化为一维数组后,dp[ j ]dp[\ j\ ]需要更新过的、可能已经含有第 ii 种物品的 dpdp 数组。
#include<iostream>
#include<algorithm>
using namespace std;
const int N =1010;
int n,m;
int f[N],v[N],w[N];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>v[i]>>w[i];
for(int i=1;i<=n;i++)
for(int j=v[i];j<=m;j++)
f[j]=max(f[j],f[j-v[i]]+w[i]);
cout<<f[m];
return 0;
}