这道题的思路十分的简单。
大于等于c的面额每周付一次,即面额数等于周数。
剩下的小于c的面额,从大到小取钱,未到c的用从小到大的面额填充,从而减少浪费。
但是明白了题目的套路还不够,实现起来有一些小困难。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <functional>
using namespace std;
typedef pair<int, int> P;
const int INF = 10e6 + 10;
P allo[25];
int need[25];
int main()
{
int n, c;
scanf("%d%d", &n, &c);
int weeks = 0;
for (int i = 0; i < n; i++) {
scanf("%d%d", &allo[i].first, &allo[i].second);
if (allo[i].first >= c) {
weeks += allo[i].second;
allo[i].second = 0;
}
}
sort(allo, allo + n, greater<P>());
while (1) {
int tmp = c;
memset(need, 0, sizeof(need));
for (int i = 0; i < n; i++) {
if (allo[i].second == 0)
continue;
int k = tmp / allo[i].first;
int u = min(k, allo[i].second);
tmp -= u * allo[i].first;
need[i] = u;
if (tmp <= 0)
break;
}
if (tmp > 0) {
for (int i = n; i >= 0; i--) {
while (need[i] < allo[i].second) {
tmp -= allo[i].first;
need[i]++;
if (tmp <= 0)
break;
}
if (tmp <= 0)
break;
}
}
if (tmp > 0)
break;
int add = INF;
for (int i = n - 1; i >= 0; i--) {
if (need[i])
add = min(add, allo[i].second / need[i]);
}
weeks += add;
for (int i = n - 1; i >= 0; i--) {
if (need[i])
allo[i].second -= add * need[i];
}
}
printf("%d\n", weeks);
return 0;
}