完全背包

完全背包:

在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,原因是,当去顺序枚举体积,已经隐含着某类物品可以放多个。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值