题目描述
经典的完全背包问题
算法1
(最朴素的dp) $O(n^3)$
照着多重背包的思路,依次更新
时间复杂度
注意事项
1,依次枚举的时候记得考虑有没有超过背包的容积
C++ 代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1010;
int f[maxn][maxn];
int v[maxn];
int w[maxn];
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>v[i];
cin>>w[i];
}
for(int i=1;i<=n;i++)
for(int j=0;j<=m;j++)
{
f[i][j]=f[i-1][j];
for(int k=0;k*v[i]<=j;k++)
{
f[i][j]=max(f[i][j],f[i-1][j-k*v[i]]+k*w[i]);
}
}
printf("%d\n",f[n][m]);
return 0;
}
算法2
(dp) $O(n^2)$
由递推公式
f[i][j]=f[i-1][j];由上一层转移过来最基本的最大值
if(j>=v[i]) f[i][j]=max(f[i][j),f[i-1][j-v[i]]+w[i]);
公式推导:
f[i][j]=max(f[i][j], f[i-1][j-v[i]]+w[i], ....f[i-1][j-kv[i]]+kw[i].......);
f[i][j-v[i]]=max( f[i-1][j-v[i]].......f[i-1][j-kv[i]]+(k-1)w[i] );
时间复杂度
C++ 代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1010;
int f[maxn][maxn];
int v[maxn];
int w[maxn];
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>v[i];
cin>>w[i];
}
for(int i=1;i<=n;i++)
for(int j=0;j<=m;j++)
{
f[i][j]=f[i-1][j];
if(j>=v[i])
{
f[i][j]=max(f[i][j],f[i][j-v[i]]+w[i]);
}
}
printf("%d\n",f[n][m]);
return 0;
}
注意事项
一维时候记得从前往后枚举
c++一维的代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1010;
int f[maxn];
int v[maxn];
int w[maxn];
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>v[i];
cin>>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]);
printf("%d\n",f[m]);
return 0;
}