看完背包九讲的多重背包之后,这题目应该可以轻松做出来了

模型:

有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

方法:

基本算法

这题目和完全背包问题很类似。基本的方程只需将完全背包问题的方程略微一改即可,因为对于第i种物品有n[i]+1种策略:取0件,取1件……取n[i]件。令f[i][v]表示前i种物品恰放入一个容量为v的背包的最大权值,则有状态转移方程:

f[i][v]=max{f[i-1][v-k*c[i]]+k*w[i]|0<=k<=n[i]}

复杂度是O(V*Σn[i])。

转化为01背包问题

另一种好想好写的基本方法是转化为01背包求解:把第i种物品换成n[i]件01背包中的物品,则得到了物品数为Σn[i]的01背包问题,直接求解,复杂度仍然是O(V*Σn[i])。

但是我们期望将它转化为01背包问题之后能够像完全背包一样降低复杂度。仍然考虑二进制的思想,我们考虑把第i种物品换成若干件物品,使得原问题中第i种物品可取的每种策略——取0..n[i]件——均能等价于取若干件代换以后的物品。另外,取超过n[i]件的策略必不能出现。

方法是:将第i种物品分成若干件物品,其中每件物品有一个系数,这件物品的费用和价值均是原来的费用和价值乘以这个系数。使这些系数分别为 1,2,4,...,2^(k-1),n[i]-2^k+1,且k是满足n[i]-2^k+1>0的最大整数。例如,如果n[i]为13,就将这种 物品分成系数分别为1,2,4,6的四件物品。

分成的这几件物品的系数和为n[i],表明不可能取多于n[i]件的第i种物品。另外这种方法也能保证对于0..n[i]间的每一个整数,均可以用若干个系数的和表示,这个证明可以分0..2^k-1和2^k..n[i]两段来分别讨论得出,并不难,希望你自己思考尝试一下。

这样就将第i种物品分成了O(log n[i])种物品,将原问题转化为了复杂度为<math>O(V*Σlog n[i])的01背包问题,是很大的改进。

以上内容来自背包九讲之多重背包问题

#include<iostream>
#include<algorithm>
#define maxn 100010
using namespace std;
int dp[maxn],n,k;
int v[101],w[101],V;
void zero(int cost)
{for(int i=V;i>=cost;i--)dp[i]=max(dp[i],dp[i-cost]+cost);
}
void complet(int cost)
{for(int i=cost;i<=V;i++)dp[i]=max(dp[i],dp[i-cost]+cost);
}
void multi(int cost,int amount)
{if(cost * amount>=V){complet(cost);return ;}int k=1;while(k<amount){zero(k*cost);amount-=k;k<<=1;}zero(amount*cost);
}
int main()
{while(scanf("%d %d",&n,&V)==2&&(n||V)){for(int i=0;i<n;i++)scanf("%d",&v[i]);for(int i=0;i<n;i++)scanf("%d",&w[i]);for(int i=1;i<=V;i++)dp[i]=INT_MIN;dp[0]=0;for(int i=0;i<n;i++)multi(v[i],w[i]);int count=0;for(int i=1;i<=V;i++)if(dp[i]>=0)count++;printf("%d\n",count);}return 0;
}

转载于:https://www.cnblogs.com/nanke/archive/2011/11/30/2269080.html

hdu2844 Coins(普通的多重背包 + 二进制优化)相关推荐

  1. [多重背包+二进制优化]HDU1059 Dividing

    题目链接 题目大意: 两个人要把一堆宝珠,在不能切割的情况下按照价值平分,他们把宝珠分成6种价值,每种价值的宝珠n个. n<=200000 思考: 首先如果加和下来的价值是一个偶数 那么还分毛啊 ...

  2. zcmu-1919: kirito(多重背包——二进制优化)

    Description 主角kirito是使用世界首款完全潜行游戏"刀剑神域(Sword Art Online)"的玩家.曾经很幸运的参与过封闭测试,并买下正式版的kirito,正 ...

  3. HDU 5445 Food Problem 多重背包+二进制优化

    据说也可以用单调队列优化多重背包,但是我不会,所以还是选择了二进制优化... 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5445 题意:先给n,m, ...

  4. POJ 1014 Dividing【多重背包+二进制优化】

    大意: 价值1, 2, 3, --, 6的物品分别a1, a2, --, a5, a6件 问能否把这些物品分成两份,使其具有相同的价值(所有物品必须全部用上) 分析: 给个物品有多件,即多重背包 只要 ...

  5. Dividing(多重背包二进制优化)

    题意:有价值为1-6的六种玻璃球,现在告诉你各种玻璃球的个数,问能否将这些玻璃球分成两份,使得两份的总价值相等 既然要等分,那么总价值必定是偶数,所以价值和为奇数是无法等分. 但价值和为偶数时,我们可 ...

  6. 12.14补卡,多重背包二进制优化

    题目链接:22背包专题 [Cloned] - Virtual Judge (vjudge.net) 思路:多重背包的主要思路就是把每一个物品分开放,从而达到每个物品拿与不拿全部遍历到.但是当物品数量过 ...

  7. ZCMU-1919 kirito's 星爆气流斩(多重背包+二进制优化)

    Problem C: kirito's 星爆气流斩 Time Limit: 2 Sec  Memory Limit: 128 MB Submit: 148  Solved: 37 [Submit][S ...

  8. ZCMU 1919: kirito's 星爆气流斩(多重背包+二进制优化)

    1919: kirito's 星爆气流斩 Time Limit: 2 Sec  Memory Limit: 128 MB Description 主角kirito是使用世界首款完全潜行游戏" ...

  9. hdu 2191 (多重背包二进制优化)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=2191 实现代码: #include<bits/stdc++.h> using namespac ...

最新文章

  1. 赠书 | 手把手教你自己动手打造一个智能恒温器
  2. windbg 如何再内核模式调试用户空间的程序
  3. python自学流程-Python系统学习流程图,教你一步步学习python
  4. k8命令,pod的启动流程与资源文件书写,k8s集群调度
  5. Android传感器编程带实例
  6. mathematica练习程序(图像取反)
  7. postman mysql_postman连接mysql执行操作
  8. 简述arm linux内核启动流程,Linux内核启动过程和Bootloader(总述)
  9. esxi 5.5运行linux拯救模式,启用Esxi 5.5 SSH 功能
  10. 我做自媒体每日的工作时间安排
  11. iOS 仿淘宝实现商品规格图片的放大缩小功能
  12. FastAdmin 开发环境详细设置 (2017)
  13. sklearn交叉验证2-【老鱼学sklearn】
  14. JointJs快速入门
  15. matlab自适应高斯核
  16. pythonqq机器人酷q_基于python和酷Q的QQ机器人开发实践(1)
  17. 基于python的简易安卓小外挂制作
  18. 策略模式(策略设计模式)详解
  19. 怎样学好英语?(多年英语学习经验总结)
  20. Problem - 1335E2 - Codeforces(暴力+优化)

热门文章

  1. installshield 脚本 在卸载过程执行_Linux下运行Jmeter脚本
  2. Python笔记-类的单例模式及重载打印
  3. Arduino笔记-对开关的基本认识
  4. C++|Qt工作笔记-Windows平台下的句柄与Qt中QWindow::winId()以及 QPlatformWindow::handle的区别与联系
  5. 6.6.1最优二叉树(赫夫曼树)
  6. java 多线程日志_多线程 打印的日志出现重复行
  7. pandas分组计算平均值_pandas索引,分组计算
  8. 【算法刷题1】二叉树的前序遍历
  9. JS学习笔记6-JavaScript 数据类型
  10. portable-config-maven-plugin 实现replace-package