01背包
01背包:有n种物品与承重为m的背包。每种物品只有一件,每个物品都有对应的重量weight[i]与价值val[i],求解如何装包使得价值最大。
时间复杂度:O(N*V)
空间复杂度:O(V)
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+7;
int dp[N];
int weight[N];
int val[N];
int main()
{
//yyy_3y
int n,m; scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&weight[i]);
for(int i=1;i<=n;i++) scanf("%d",&val[i]);
for(int i=1;i<=n;i++)
{
for(int j=m;j>=weight[i];j--)
{
dp[j]=max(dp[j],dp[j-weight[i]]+val[i]);
}
}
printf("%d\n",dp[m]);
return 0;
}
完全背包
完全背包:有n种物品与承重为m的背包。每种物品有无限多件,每个物品都有对应的重量weight[i]与价值val[i],求解如何装包使得价值最大。
完全背包问题与01背包问题的区别在于完全背包每一件物品的数量都有无限个,而01背包每件物品数量只有1个。从策略角度上来说,相比01背包只有取和不取,完全背包可以不取,取1个,2个等等。
时间复杂度:O(N*V)
空间复杂度:O(V)
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+7;
int dp[N];
int weight[N];
int val[N];
int main()
{
//yyy_3y
int n,m; scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&weight[i]);
for(int i=1;i<=n;i++) scanf("%d",&val[i]);
for(int i=1;i<=n;i++)
{
for(int j=weight[i];j<=m;j++)
{
if(weight[i]<=j)
dp[j]=max(dp[j],dp[j-weight[i]]+val[i]);
}
}
printf("%d\n",dp[m]);
return 0;
}
多重背包
多重背包:有n种物品与承重为m的背包。每种物品有有限件num[i],每个物品都有对应的重量weight[i]与价值value[i],求解如何装包使得价值最大。
可以把每个物品拆开,把相同的num[i]件物品,看成价值跟重量相同的num[i]件不同的物品,姐可以转化为01背包了。
时间复杂度:O(N*V*V)
空间复杂度:O(V)
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+7;
int dp[N];
int weight[N];
int val[N];
int num[N];
int main()
{
//yyy_3y
int n,m; scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&weight[i]);
for(int i=1;i<=n;i++) scanf("%d",&val[i]);
for(int i=1;i<=n;i++) scanf("%d",&num[i]);
for(int i=1;i<=n;i++)
{
for(int k=0;k<num[i];k++)
{
for(int j=m;j>=weight[i];j++)
{
dp[j]=max(dp[j],dp[j-weight[i]]+val[i]);
}
}
}
printf("%d\n",dp[m]);
return 0;
}