题目
按照生活中找钱的顺序。假设还没找的钱为last,总是先在零钱里找面值小于last中最大的。如果最后last大于零钱的最小面值,应该优先找最小面值(找不开了,少亏一点是一点)。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <iomanip>
#include <queue>
#include <map>
#include <cstring>
#include <algorithm>
using namespace std;
struct Coin{
int val;
int num;
};
typedef long long ll;
int N, C;
Coin coin[21];
bool Cmp(Coin a, Coin b)
{
return a.val > b.val;
}
int main(void)
{
cin >> N >> C;
ll sum = 0;//记录所有零钱的总个数
for (int i = 0; i < N; i++) {
cin >> coin[i].val >> coin[i].num;
sum += coin[i].num;
}
sort(coin, coin + N, Cmp);//排序,按照面值从大到小
ll ans = 0;
while (true) {
int last = C;//还没找的钱
int idx = 0;//下标,用于剪枝
while (last > 0 && sum > 0) {
bool flag = false;//标记
for (int i = idx; i < N; i++) {//last >= 最小面值
if (last >= coin[i].val && coin[i].num > 0) {//在剩余所有面值的零钱找最大的
last -= coin[i].val;
coin[i].num--, sum--;
idx = i;//记录下标,如果last仍然>=最小面值,下次找的时候,idx前面的面值都太大了
flag = true;//标记
break;
}
}
if (flag) {//如果找到就返回
continue;
}
for (int i = N - 1; i >= 0; i--) {// last < 最小面值
if (last < coin[i].val && coin[i].num > 0) {//再剩下的零钱里找面值最小的
last -= coin[i].val;
coin[i].num--, sum--;
break;
}
}
}
if (last <= 0) { //还没找的钱应该小于等于0
ans++;
}
if (sum == 0) {//没有零钱了
break;
}
}
cout << ans << endl;
return 0;
}