完全背包

来源:互联网 发布:魔侠传 网络异常 编辑:程序博客网 时间:2024/06/05 09:26

完全背包:

在N物品中选取若干件(同一种物品可多次选取),放在体积为V的背包里,每物品的体积为w1,w2......wn,与之相对应的价值为v1,v2......vn,求解怎么装物品可使背包里物品总价值最大?

动态规划:

dp[i][j]表示前i物品中选取若干件物品放入体积为j的背包中所能得到的最大价值。

状态转移方程:

dp[i][j] = max(dp[ i - 1 ][ j - k * w[i] ] + k * v[i]),0 <= k * w[i] <= j

其中dp[ i - 1 ][ j - k * w[i] ] + k * v[i]表示从前i-1物品中选取若干件物品放入体积为j - k * w[i]的背包中所能得到的最大价值加上k件第i物品的价值。

如果直接按照此状态转移方程进行dp,会有三层循环,复杂度为O(NV∑(j/w[i])),可以基于01背包的思想进行多个优化,最后的复杂度为O(NV)。

实现:

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int dp[10000];int w[100],v[100];//体积 价值int main(){  int N,V;  memset(dp,0,sizeof(dp));  scanf("%d%d",&N,&V);  for(int i = 1;i <= N;i++){    scanf("%d%d",&w[i],&v[i]);  }  for(int i = 1;i <= N;i++){    for(int j = w[i];j <= V;j++){       dp[j] = max(dp[j],dp[j - w[i]] + v[i]);    }  }  return 0;}

优化一:采用一维数组,空间复杂度更低。不同于01背包的是,01背包采用一维数组体积需要逆序,而此处为顺序。原因是可以重复放置物品。

优化二:减少了枚举k这层循环,时间复杂度更低。不用去枚举k,原因是,当去顺序枚举体积,已经隐含着某类物品可以放多个。