基础问题背包类.pptVIP

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
基础问题:01背包 有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。 特点是:每种物品仅有一件,可以选择放或不放。 状态转移方程f[i][v]= max{f[i-1][v],f[i-1][v-c[i]]+w[i]} 初始化: (1) 不要求背包放满 for v=0…V f[0][v]=0; (2)要求背包放满 f[0][0]为0其它f[0][1..V]均设为-∞ 时间和空间复杂度均为O(VN) 优化空间复杂度 (二维转一维) for i=1..N for v=V..0 (不是0..V) f[v]=max{f[v],f[v-c[i]]+w[i]};  在每次主循环中f[v]保存着f[i-1][v]的值 由于费用为cost的物品不会影响状态f[0..cos1],因为装不下。 void ZeroOne(int cost,int weight)//处理一个物品 { int v; for(v=V;v=cost;v--) f[v]=max(f[v],f[v-cost]+weight); } for(i=1;i=n;i++)//处理所有物品 ZeroOne(c[i],w[i]); 完全背包问题 每种物品都有无限件可用 方程:f[i][v]=max{f[i-1][v-k*c[i]]+k*w[i]|0=k*c[i]=v} 每件物品并非取或不取两种,而是有取0件、取1件、取2件……等很多种。 求解状态f[i][v]的时间是O(v/c[i]),总的复杂度可以认为是O(V*Σ(V/c[i])),需要优化 一个简单有效的优化 若两件物品i、j满足c[i]=c[j]且w[i]=w[j],则将物品j去掉,不用考虑。需要O(N^2)的时间 另一个思路:转化为01背包问题求解 即:将一种物品拆成多件物品。 更高效的转化方法 把第i种物品拆成费用为c[i]*2^k、价值为w[i]*2^k的若干件物品,其中k满足c[i]*2^k=V。 但我们有更优的O(VN)的算法。 for i=1..N for v=0..V f[v]=max{f[v],f[v-cost]+weight} 这个伪代码与01背包的伪代码只有v的循环次序相反而已 值得一提的是,上面的伪代码中两层for循环的次序可以颠倒。这个结论有可能会带来算法时间常数上的优化。 void Complete(int cost,int weight) )//处理一个物品 { int v; for(v=cost;v=V;v++)(cost理由同01) f[v]=max(f[v],f[v-cost]+weight); } for(i=1;i=n;i++)//处理所有物品 Complete (c[i],w[i]); 多重背包问题 第i种物品最多有n[i]件可用 基本算法: 和完全背包问题很类似。对于第i种物品有n[i]+1种策略:取0件,取1件……取n[i]件。状态转移方程: f[i][v]=max{f[i-1][v-k*c[i]]+k*w[i]|0=k=n[i]} 复杂度是O(V*Σn[i])。 优化:转化为01背包问题 方法是:将第i种物品分成若干件物品. 分别为1,2,4,...,2^(k-1),n[i]-2^k+1,且k是满足n[i]-2^k+10的最大整数。例如,如果n[i]为13,就将这种物品分成系数分别为1,2,4,6的四件物品。 这样就将第i种物品分成了O(log n[i])种物品将原问题转化为了复杂度为O(V*Σlog n[i])的01背包问题, 伪代码:处理一个物品 MultiplePack(cost,weight,amount) if cost*amount=V Complete (cost,weight) else k=1 while kamount ZeroOnePack(k*cost,k*weight) amount=amount-k k=k*2 ZeroOnePack(amount*cost,amount*weight) void Multiple(int cost,int weight,int amount) { if(amount*cost=V) Complete(cost,weight); else { int k=1; while(kamount) { ZeroOne(cost*k

文档评论(0)

雨中人 + 关注
实名认证
文档贡献者

这一世渡尽红尘,若有来生,不再为人。

1亿VIP精品文档

相关文档