C - Otoshidama
传送门:https://abc085.contest.atcoder.jp/tasks/abc085_c
有面值为10000、5000、1000(YEN)的纸币。试用N张纸币,组成金额为Y(YEN)的钱。
依次考虑:
1.只用1KYEN的纸币;
2.用1KYEN和5KYEN的纸币;
3.用1KYEN、5KYEN和10KYEN的纸币。
参考程序如下:
#include <stdio.h> int min(int a, int b) { return a < b? a: b; } int main(void) { int n, y; scanf("%d%d", &n, &y); //1k-yen only. int yen_1k = y / 1000; int yen_5k = 0; int yen_10k = 0; int cnt = yen_1k + yen_5k + yen_10k; if (cnt == n) printf("%d %d %d ", yen_10k, yen_5k, yen_1k); else if (cnt < n) printf("-1 -1 -1 "); //1k-yen and 5k-yen. else { int dif = cnt - n; int y1k_2_y5k = min(dif / 4, yen_1k / 5); yen_5k += y1k_2_y5k; yen_1k -= y1k_2_y5k * 5; cnt = yen_1k + yen_5k + yen_10k; if (cnt == n) printf("%d %d %d ", yen_10k, yen_5k, yen_1k); //1k-yen, 5k-yen and 10k-yen. else { dif = cnt - n; int y5k_2_y10k = min(dif, yen_5k / 2); yen_10k += y5k_2_y10k; yen_5k -= y5k_2_y10k * 2; cnt = yen_1k + yen_5k + yen_10k; if (cnt == n) printf("%d %d %d ", yen_10k, yen_5k, yen_1k); else printf("-1 -1 -1 "); } } return 0; }
当然,这个问题也可以构造一个三元一次方程,brute force求解。
D - Katana Thrower
传送门:https://abc085.contest.atcoder.jp/tasks/abc085_d
有N把武士刀,对于每一把武士刀,有以下两种攻击方法:
①常规:攻击造成a点damage,可连续多次使用;
②终结:攻击造成b点damage,使用一次后丢弃。
对于每一把武士刀,有a≤b。
为造成至少H点的damage,求最小攻击次数。
设置一个优先队列(用std::priority_queue实现),对于每一把武士刀,将有序对<a,1>和<b,0>置入优先队列。于是,每次取出顶端的元素,作为武器使用。
参考程序如下:
#include <bits/stdc++.h> using namespace std; priority_queue<pair<int, bool> > q; int main(void) { int n, h; scanf("%d%d", &n, &h); for (int i = 0; i < n; i++) { int a, b; scanf("%d%d", &a, &b); q.push(make_pair(a, 1)); q.push(make_pair(b, 0)); } int ans = 0; while (h > 0) { int attack = q.top().first; bool multi_attack = q.top().second; q.pop(); if (multi_attack) { int cnt = h / attack; if (h % attack) cnt++; h -= attack * cnt; ans += cnt; } else { h -= attack; ans++; } } printf("%d ", ans); return 0; }