From f44a9ff3b7e3b8d014a0d9e98ba4aa540a36c720 Mon Sep 17 00:00:00 2001 From: Kirito <1362050620@qq.com> Date: Thu, 21 Apr 2016 09:36:07 +0800 Subject: [PATCH] From www.hankcs.com/program/cpp/poj-3040-allowance.html --- POJ/3040_hankcs.cpp | 102 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 POJ/3040_hankcs.cpp diff --git a/POJ/3040_hankcs.cpp b/POJ/3040_hankcs.cpp new file mode 100644 index 0000000..caa36f3 --- /dev/null +++ b/POJ/3040_hankcs.cpp @@ -0,0 +1,102 @@ +#include +#include +#include +#include +using namespace std; + +typedef pair Coin; // 硬币 面值和数量 +Coin coin[20]; +int need[20]; + +///////////////////////////SubMain////////////////////////////////// +int main(int argc, char *argv[]) +{ +#ifndef ONLINE_JUDGE + freopen("in.txt", "r", stdin); + freopen("out.txt", "w", stdout); +#endif + int N, C; + cin >> N >> C; + for (int i = 0; i < N; ++i) + { + cin >> coin[i].first >> coin[i].second; + } + int week = 0; + // 面额不小于C的一定可以支付一周 + for (int i = 0; i < N; ++i) + { + if (coin[i].first >= C) + { + week += coin[i].second; + coin[i].second = 0; + } + } + sort(coin, coin + N, greater()); + while(true) + { + int sum = C; // 等待凑足的sum + memset(need, 0, sizeof(need)); + // 从大到小 + for (int i = 0; i < N; ++i) + { + if (sum > 0 && coin[i].second > 0) + { + int can_use = min(coin[i].second, + sum / coin[i].first); + if (can_use > 0) + { + sum -= can_use * coin[i].first; + need[i] = can_use; + } + } + } + // 从小到大 + for (int i = N - 1; i >= 0; --i) + { + if (sum > 0 && coin[i].second > 0) + { + int can_use = min(coin[i].second - need[i], // 上个loop用掉了一些 + (sum + coin[i].first - 1) / coin[i].first); // 允许多出不超过一个面值的金额 + if (can_use > 0) + { + sum -= can_use * coin[i].first; + need[i] += can_use; + } + } + } + + if(sum > 0) + { + break; + } + + int add_up = numeric_limits::max(); // 凑起来的week数 + // add_up多少个最优的week 受限于 每种面值能满足最优解下的需求个数多少次 + for (int i = 0; i < N; ++i) + { + if (need[i] == 0) + { + continue; + } + add_up = min(add_up, coin[i].second / need[i]); + } + week += add_up; + // 最优解生效,更新剩余硬币数量 + for (int i = 0; i < N; ++i) + { + if (need[i] == 0) + { + continue; + } + coin[i].second -= add_up * need[i]; + } + } + cout << week << endl; +#ifndef ONLINE_JUDGE + fclose(stdin); + fclose(stdout); + system("out.txt"); +#endif + return 0; +} +///////////////////////////End Sub//////////////////////////////////