暑假- 动态规划 I-(N - Coins)
2015-07-21 20:49
369 查看
/* 多重背包问题:一般化为01背包[逆序]和完全背包[顺序]来求解 多重背包优化:二进制原理。 dp[i]表示:容量为i的背包在限制条件下[硬币的面值和数量]所能获得的最大值 此题中的每个硬币的体积[重量]和价值[面值]是同一个数[a]。 当dp[i]==i时,表示容量为i的背包可以装下价值为i的物品,即相当于能够用所限的 硬币凑足i。最后再扫一遍数组就能得出结果。 */ #include<iostream> using namespace std; const int MAXN=100005; struct Node { int a; int c; }; int dp[MAXN]; int mymax(int a,int b) { return a>b?a:b; } void CompletePack(int w,int m)//完全背包(顺序求解,w即使重量也是价值) { for(int i=w;i<=m;i++) { dp[i]=mymax(dp[i],dp[i-w]+w); } } void ZeroOnePack(int w,int m)//01背包(逆序求解,w即使重量也是价值) { for(int i=m;i>=w;i--) { dp[i]=mymax(dp[i],dp[i-w]+w); } } void MultiPack(int w,int c,int m) { if(w*c>=m)//面值*数目〉所要凑得面值(相当于有无限多个面值为w的硬币可用) { CompletePack(w,m);//多重背包-->完全背包 } else//否则,多重背包-->01背包 { //二进制原理转换成01背包求解。 int k=1; while(c-k>0) { ZeroOnePack(w*k,m); c-=k; k*=2; } ZeroOnePack(w*c,m);//剩下的硬币数目 } } int main() { int n,m; while(cin>>n>>m) { if(!n&&!m) { break; } int temp=0;//统计能凑齐的数目 Node p[105]; memset(dp,0,sizeof(dp)); for(int i=0;i<n;i++)//录入面值 { cin>>p[i].a; } for(int i=0;i<n;i++)//录入数目 { cin>>p[i].c; } for(int i=0;i<n;i++) { MultiPack(p[i].a,p[i].c,m); } for(int i=1;i<=m;i++)//扫描统计 { if(dp[i]==i) { temp++; } } cout<<temp<<endl; } return 0; }
一般将多重背包转换成01背包和完全背包求解。
多重背包问题:二进制原理,单调队列。
相关文章推荐
- 深度搜索算法(POJ 3984)
- 关于java基础--基本数据类型封装以及String类方法讲解
- 初窥Python(一)——使用pymongo连接MongoDB
- 工作积累(三)——使用jQuery实现回车触发事件
- 多学一点(十四)——服务器间通过rsync和inotify-tools动态同步数据
- 工作积累(二)——使用java.util.ResourceBundle和java.util.Properties实现常量功能
- JavaScript中的slice()和splice()
- 多学一点(十三)——解决Linux kdump服务启动失败
- 多学一点(十一)——配置使用Tomcat Manager进行可视化部署
- 多学一点(十)——配置一个Tomcat使其可以多端口访问
- JavaScript中的函数声明和函数表达式
- 工作积累(一)——使用canvas实现前台图片base64转码
- JavaScript中的面向对象(一)——创建自定义对象
- 探秘Node.js(一)——Node.js简介及安装配置
- 多学一点(九)——使用touch命令创建指定时间的文件
- 学习笔记(十一)——Linux Shell 基础知识
- 多学一点(八)——LNMP环境搭建
- NSString
- 多学一点(五)——在Linux下安装配置Apache
- 多学一点(六)——在Linux下安装配置MySQL