关于一维背包和完全背包问题都会在这进行讲解
首先一维背包,如何从二维背包中转换,我们可以从原先的代码提取一点信息
#include<bits/stdc++.h> using namespace std; int a[1010]; int w[1010]; int v,m; int dp[1500][1500]; int main() { cin>>v>>m; for(int i=1;i<=m;i++) { cin>>a[i]>>w[i]; } for(int i=1;i<=m;i++) { for(int j=v;j>=1;j--) { if(j<a[i]) dp[i][j]=dp[i-1][j]; else dp[i][j]=max(dp[i-1][j],dp[i-1][j-a[i]]+w[i]); } } // for(int i=1;i<=m;i++) // { // for(int j=1;j<=v;j++) // { // cout<<dp[i][j]<<" "; // } // cout<<endl; // } cout<<dp[m][v]<<endl; return 0; }
我们可以看到他是每次都从i-1中提取出来的,那么现在不用i-1直接用后边那个j来表示的结果,如下图所示其中次数代表着外层循环,第i次的f数组的所有元素值。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int v[10010];
int w[10010];
int a[10010];
int main()
{
int n,m;
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=m;j>=v[i];j--)
{
a[j]=max(a[j],a[j-v[i]]+w[i]);
}
}
cout<<a[m];
return 0;
}
其中动态转移方程是倒着写推的,他的目的是不重复利用同一个物品,那完全背包是什么,就是同一个物品可以利用多次,所以我们的动态转移方程就可以正着写,直接借鉴01背包问题,附赠一个推导图,多推导几次就差不多能会。(上边的为01背包,下边的为完全背包,放在一起方便对比)
#include<bits/stdc++.h>
using namespace std;
int a[11];
int f[100010];
int main()
{
int n=10;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
int m;
cin>>m;
f[0]=0;
for(int i=1;i<=m;i++)
{
f[i]=i*a[1];
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(j-i>=0)
f[j]=min(f[j],f[j-i]+a[i]);
}
}
cout<<f[m]<<endl;
return 0;
}