思路:
每次放钱的时候,遵循两个原则来寻找最优方案:
1. 不能用面额小的组成面额大的
2. 所有方案中取最接近 C 的那个
就这样一次次的放,放到没钱为止。
注意,由于货币的数量较大,如果最优方案可以执行多次,那就一次过执行完。
#include <stdio.h>
#include <stdlib.h>
#define MAX_N 64
struct node {
int val, cnt;
};
struct node coin[MAX_N];
int N, C, best, best_idx, ans, need[MAX_N];
inline int min(int a, int b)
{
return a < b ? a : b;
}
int cmp(const void *a, const void *b)
{
return ((struct node *)a)->val - ((struct node *)b)->val;
}
inline int put(int idx, int val)
{
int n;
n = min(coin[idx].cnt, (C - val - 1) / coin[idx].val);
val += coin[idx].val * n;
if (coin[idx].cnt > n) {
if (!best || val + coin[idx].val < best) {
best = val + coin[idx].val;
best_idx = idx;
}
}
need[idx] = n;
return val;
}
inline int can()
{
int i, val;
best = val = 0;
for (i = N - 1; i >= 0; i--)
val = put(i, val);
return best;
}
inline void update()
{
int i, cnt;
cnt = 100000000;
need[best_idx]++;
for (i = N - 1; i >= best_idx; i--)
if (need[i])
cnt = min(cnt, coin[i].cnt / need[i]);
for (i = N - 1; i >= best_idx; i--)
coin[i].cnt -= cnt * need[i];
ans += cnt;
}
int main()
{
int i;
scanf("%d%d", &N, &C);
for (i = 0; i < N; i++)
scanf("%d%d", &coin[i].val, &coin[i].cnt);
qsort(coin, N, sizeof(coin[0]), cmp);
while (coin[N - 1].val >= C) {
ans += coin[N - 1].cnt;
N--;
}
while (can())
update();
printf("%d\n", ans);
return 0;
}