POJ 1276 Cash Machine 多重背包问题
2015-08-30 14:42
405 查看
题目
看完了《背包九讲》,找个OJ练练手。原题参考: http://poj.org/problem?id=1276
大意是:一个取款机有
N种钞票,每种钞票有
nk张,面额为
Dk,给定一个取款金额
cash,可行的、不超过该金额的吐钞方案是多少钱?
解法
多重背包问题的变体,参考《背包九讲》。变体的地方仅仅是:价格和代价合一。代码
很容易写出普通的版本(Version 1),写着写着才想到其实价值并不需要存储下来,仅仅知道体积恰好为V的多重背包是否可行(有解)即可。为什么呢?因为解就是V本身。于是又改了一下变成位运算的版本(Version 2),常数优化。
Version 1
#include <algorithm> #include <iostream> #include <climits> using namespace std; int cash, n; int money[10]; int bills[10]; int dp[100001]; void complete_pack(int w) { for (int i = w; i <= cash; i++) { dp[i] = max(dp[i], dp[i - w] + w); } } void zero_one_pack(int w) { for (int i = cash; i >= w; i--) { dp[i] = max(dp[i], dp[i - w] + w); } } void multiple_pack(int w, int n) { if (w * n >= cash) { complete_pack(w); } else { int k = 1; while (n > 0) { zero_one_pack(k*w); n -= k; if (k * 2 <= n) k *= 2; else k = n; } } } int main() { while (cin >> cash) { cin >> n; memset(dp, 0, sizeof(dp)); for (int i = 0; i < n; i++) { cin >> bills[i] >> money[i]; multiple_pack(money[i], bills[i]); } for (int i = cash; i >= 0; i--) { if (dp[i] == i) { printf("%d\n", i); break; } } } }
Version 2
#include <algorithm> #include <iostream> #include <climits> using namespace std; int cash, n; int money, bills; bool dp[100001]; void complete_pack(int w) { for (int i = w; i <= cash; i++) { dp[i] = dp[i] || dp[i - w]; } } void zero_one_pack(int w) { for (int i = cash; i >= w; i--) { dp[i] = dp[i] || dp[i - w]; } } void multiple_pack(int w, int n) { if (w * n >= cash) { complete_pack(w); } else { int k = 1; while (n > 0) { zero_one_pack(k*w); n -= k; if (k * 2 <= n) k *= 2; else k = n; } } } int main() { while (cin >> cash) { cin >> n; memset(dp, 0, sizeof(dp)); dp[0] = true; for (int i = 0; i < n; i++) { cin >> bills >> money; multiple_pack(money, bills); } for (int i = cash; i >= 0; i--) { if (dp[i]) { printf("%d\n", i); break; } } } }
相关文章推荐
- Java队列学习(一)
- 关于listView中的自定义以后不响应onItemClick事件的解决方法
- C#生成唯一值的方法汇总
- 【原创】leetCodeOj --- Sliding Window Maximum 解题报告
- The Java EE 6 Tutorial Filtering Requests and Responses
- 与NULL有关的函数
- MongoDB (七) MongoDB 数据类型
- C#中怎么复制数组
- Linux学习之btrfs文件系统
- Hadoop学习-错误记录
- Django之第一个app<16>
- STL1——顺序容器和顺序容器适配器
- JS与PHP互通的RSA加解密
- 常见的开源协议
- centos的软件安装方法rpm和yum
- RadioGroup、RadioButton以及Spinner学习笔记
- HDU5025--Saving Tang Monk(BFS)
- 指针和数组的一个例子
- JS事件
- Activity跳转与传值