https://vjudge.csgrandeur.cn/problem/POJ-3040

/*
作为创纪录的牛奶产量的奖励,约翰决定每周给贝西一小笔零用钱。FJ拥有一组N(1 <= N <= 20)种不同面额的硬币,
其中每个面额的硬币均可整除较大面额的硬币(例如,1分硬币、5分硬币、10分硬币和50分硬币)。
使用给定的硬币面额,他想每周至少支付给贝西一定金额C(1 <= C <= 100,000,000)。
请帮助他计算他最多可以支付贝西多少周。 输入 第1行:两个以空格分隔的整数:N和C
第2行到第N+1行:每行对应一个硬币面额,并包含两个整数:
硬币面额V(1 <= V <= 100,000,000)和约翰手中该面额的硬币数量B(1 <= B <= 1,000,000)。
输出 第1行:一个整数,表示约翰可以支付贝西至少C零用钱的周数。 3 6
10 1
1 100
5 120 111 3 6
10 3
20 4
40 5 12 3 51
100 1
50 4
1 2 4 3 51
1 2
50 4
100 1 4 20 100000000
67108864 1000000
33554432 1000000
16777216 1000000
8388608 1000000
4194304 1000000
2097152 1000000
1048576 1000000
524288 1000000
262144 1000000
131072 1000000
65536 1000000
32768 1000000
16384 1000000
8192 1000000
4096 1000000
2048 1000000
1024 1000000
512 1000000
256 1000000
128 1000000 1340054 输入详情:
FJ每周想支付给贝西6美分。他手上有100个1美分硬币,120个5美分硬币和1个10美分硬币。 输出详情:
FJ可以用一个10美分硬币多支付给贝西1周,然后用两个5美分硬币支付给贝西10周,
最后用一个1美分硬币和一个5美分硬币支付给贝西100周。
*/

解答

直觉分析如下:

因为可选择的美分硬币数值是可整除的。所以我们需要尽量选择面额更大的硬币.

1 因为面值小的硬币总能替代面额大的硬币,更优。所以我们选择次优的较大面额的硬币,将更优的选择留给后面。

2 同样的 凑齐刚好等于每周报酬的面值能留下更多的硬币数值给后面的选择,所以优先选择刚好等于每周报酬的组合,

然后再选择最接近、大于等于每周报酬的组合。

代码如下

#include <iostream>
#include <cstring>
#include <map> using namespace std; int n, c;
int ans;
map<int, int> mm;
map<int, int> usedmm;
int limit; void GetusedArr() {
//计算每次选择硬币的组合 逆序从大到小选择, 优先选择大额的 最接近等于每周报酬的组合
for (map<int, int>::reverse_iterator it = mm.rbegin(); it != mm.rend(); it++) {
if (it->second != 0 && limit >0 && limit >= it->first) {
int used = min(limit / it->first, it->second);
limit -= used * it->first;
usedmm[it->first] += used;
}
//剩余值为0 则说明抽出了刚好等于每周报酬的组合
if (limit == 0) break;
} //贪心完所有金币 还没超出需要的金额. 说明凑不出刚好等于报酬的组合
// 从小到大选择硬币,使用较小的面值进行填充 最接近等于每周报酬
if (limit > 0) {
for (map<int, int>::iterator it = mm.begin(); it != mm.end(); it++) {
if (it->second > 0 && limit > 0 && mm[it->first] > usedmm[it->first]) {
int used = 1; int v = it->first; int cnt = it->second;
limit -= v;
usedmm[v] += 1;
}
}
} return;
} void solve() { while (1) {
usedmm.clear();
limit = c;
GetusedArr();
//limit 还不等于小于0 那么说明现在的硬币已经不能凑齐一周报酬了
if (limit > 0) {
cout << ans << endl; return;
}
//按照usedmm 查看能取几次
int minget = 1000010;
for (map<int, int>::iterator it = usedmm.begin(); it != usedmm.end(); it++) {
int v = it->first;
minget = min(minget, mm[v]/it->second);
} ans += minget; //从已有的硬币里减去
for (map<int, int>::iterator it = usedmm.begin(); it != usedmm.end(); it++) {
int v = it->first;
mm[v] -= minget * it->second;
}
}
} int main()
{
cin >> n >> c; for (int i = 0; i < n; i++) {
int v, b; cin >> v >> b;
if (v >= c) {
ans += b;
}
else {
mm[v] += b;
}
} solve(); return 0;
}

我的视频题解空间

挑战程序设计竞赛 2.2 poj 3040 Allowance 贪心的更多相关文章

  1. POJ 3040 Allowance 贪心

    这题目的贪心思路还是有一点细节问题的. 还没有证明,据说是因为题目给的条件是每个价格是比它小的价格的倍数才能这么贪心的. 思路如下: 假设要给奶牛的钱为C 1)从大面值到小面值一次拿钱,能拿多少拿多少 ...

  2. POJ 2386 Lake Counting 题解《挑战程序设计竞赛》

    地址 http://poj.org/problem?id=2386 <挑战程序设计竞赛>习题 题目描述Description Due to recent rains, water has ...

  3. 《挑战程序设计竞赛》2.3 动态规划-优化递推 POJ1742 3046 3181

    POJ1742 http://poj.org/problem?id=1742 题意 有n种面额的硬币,面额个数分别为Ai.Ci,求最多能搭配出几种不超过m的金额? 思路 据说这是传说中的男人8题呢,对 ...

  4. Aizu 2249Road Construction 单源最短路变形《挑战程序设计竞赛》模板题

    King Mercer is the king of ACM kingdom. There are one capital and some cities in his kingdom. Amazin ...

  5. 挑战程序设计竞赛》P345 观看计划

                                                 <挑战程序设计竞赛>P345 观看计划 题意:一周一共有M个单位的时间.一共有N部动画在每周si时 ...

  6. poj 3253 Fence Repair 贪心 最小堆 题解《挑战程序设计竞赛》

    地址 http://poj.org/problem?id=3253 题解 本题是<挑战程序设计>一书的例题 根据树中描述 所有切割的代价 可以形成一颗二叉树 而最后的代价总和是与子节点和深 ...

  7. POJ 3040 Allowance【贪心】

    POJ 3040 题意: 给奶牛发工资,每周至少 C 元.约翰手头上有面值V_i的硬币B_i个,这些硬币的最小公约数为硬币的最小面值.求最多能发几周? 分析: 贪心策略是使多发的面额最小(最优解).分 ...

  8. 《挑战程序设计竞赛》2.2 贪心法-其它 POJ3617 3069 3253 2393 1017 3040 1862 3262

    POJ3617 Best Cow Line 题意 给定长度为N的字符串S,要构造一个长度为N的字符串T.起初,T是一个空串,随后反复进行下列任意操作: 从S的头部(或尾部)删除一个字符,加到T的尾部 ...

  9. 【网络流#8】POJ 3469 Dual Core CPU 最小割【ISAP模板】 - 《挑战程序设计竞赛》例题

    [题意]有n个程序,分别在两个内核中运行,程序i在内核A上运行代价为ai,在内核B上运行的代价为bi,现在有程序间数据交换,如果两个程序在同一核上运行,则不产生额外代价,在不同核上运行则产生Cij的额 ...

  10. <挑战程序设计竞赛> poj 3320 Jessica's Reading Problem 双指针

    地址 http://poj.org/problem?id=3320 解答 使用双指针 在指针范围内是否达到要求 若不足要求则从右进行拓展  若满足要求则从左缩减区域 代码如下  正确性调整了几次 然后 ...

随机推荐

  1. 基于百度AI平台的人脸识别评分小程序

    face-recognition-scoring-applet 开放源代码,遵循Apache License 2.0 效果展示 可切换摄像头.拍照.从相册选择 效果预览 小程序账号注册及配置 地址:h ...

  2. [GIT]解决:failed to push some refs to ...(过程重现)

    本问题有很多种情况,解决方法也很多,本文只针对笔者本人的自身诉求和情况,选择了一种适合我的解决方法.仅供参考. 1 问题描述 johnnyzen@XXDSSS MINGW64 /e/source_co ...

  3. PostgreSQL 9.6 文档: 数据类型

    章 8. 数据类型 目录 8.1. 数字类型 8.1.1. 整数类型 8.1.2. 任意精度数字 8.1.3. 浮点类型 8.1.4. 序数类型 8.2. 货币类型 8.3. 字符类型 8.4. 二进 ...

  4. 如何新建一个django项目

    1.新建项目 2选择django 3.接下来我们进入 djangotest目录输入以下命令,启动服务器: python manage.py runserver 0.0.0.0:8000 0.0.0.0 ...

  5. LCD与OLED的相爱相杀

    目前市面的显示技术主要分为LCD与OLED. 本文主要记录对LCD与OLED的学习. 导言:介绍一些专业名词和术语. 像素点:是指在由一个数字序列表示的图像中的一个最小单位,称为像素. 一张图片在显示 ...

  6. Mysql高级4-索引的使用规则

    一.最左前缀法则 如果索引了多列(联合索引),要遵守最左前缀法则.最左前缀法则指的是查询从索引的最左列开始,并且不跳过索引中的列,如果跳跃某一列,索引将部分失效(后面的字段索引失效) 示例1:acco ...

  7. 转载【Linux中建立软raid】

    原文地址:https://www.cnblogs.com/diantong/p/10547081.html Linux内核中有一个md(multiple devices)模块在底层管理RAID设备,它 ...

  8. 如何在 Windows10 下运行 Tensorflow 的目标检测?

    前言 看过很多博主通过 Object Detection 实现了一些皮卡丘捕捉,二维码检测等诸多特定项的目标检测.而我跟着他们的案例来运行的时候,不是 Tensorflow 版本冲突,就是缺少什么包, ...

  9. 利用文件包含漏洞包含ssh日志拿shell

    今天看文章学了一招,有包含漏洞无法传文件的时候用 目标服务器环境为ubuntu,ssh登录日志文件是/var/log/auth.log 找个Linux的环境执行ssh '<? phpinfo() ...

  10. js高级之内存管理与闭包

    javacript中的内存管理 javascript中不需要我们手动去分配内存,当我们创建变量的时候,会自动给我们分配内存. 创建基本数据类型时,会在栈内存中开辟空间存放变量 创建引用数据类型时,会在 ...