HDU 5527 Too Rich【思维】【贪心】

题目大意:

给你面值为1,5,10,20,50,100,200,500,1000,2000的钞票$c_1、c_2 \ldots c_{10}$,问你给出的这些钱能否恰好凑出p元来,如果可以,最多的数量是多少。

解题思路:

用给出的钱从大到小比较和p的关系凑很容易检查能否凑出p元来,这时是用的最少的数量凑的。

用最多的数量的话就是用tot - (最少的钱数凑的sum - p的数量),tot是总数量,sum是总面值和。本来以为到这里就结束了,然而满足上面这是最少使用量的前提是小面额是大面额的因子,即任意数量的大面额总能用若干小面额凑出来,而在本题中20、50,200、500不满足。对于这种情况的解法,我们可以将两个50的合成一个100的,两个500的合成一个1000的来算,但是答案可能还有用到1个50/500的情况。好在他们的搭配只有4种,这时我们只要枚举这4种情况就好了。

Mycode:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int INF = 0x3f3f3f3f;

int t, p, tot, sum;
int a[11], b[11], val[11];

void init()
{
val[0] = 1, val[1] = 5, val[2] = 10;
val[3] = 20, val[4] = 50, val[5] = 100;
val[6] = 200, val[7] = 500, val[8] = 1000;
val[9] = 2000;
}

void init2()
{
for(int i = 0; i < 10; ++i)
b[i] = a[i];
}

int solve(int num)
{
int ans = 0, tem;
for(int i = 9; i >= 0; --i)
{
if(i == 4 || i == 7)
{
tem = min(num / (val[i] * 2), b[i] / 2);
num -= tem * val[i] * 2;
ans += tem * 2;
}
else
{
tem = min(num / val[i], b[i]);
num -= tem * val[i];
ans += tem;
}
// cout << i << " " << tem << endl;
}
//cout << "ans = " << ans << '\n';
if(num) return INF;
return ans;
}

int main()
{
init();
scanf("%d", &t);
while(t--)
{
tot = sum = 0;
scanf("%d", &p);
for(int i = 0; i < 10; ++i)
{
scanf("%d", &a[i]);
tot += a[i];
sum += a[i] * val[i];
}
//cout << "tot = " << tot << " sum = " << sum << '\n';
if(sum < p)
{
puts("-1");
continue;
}

//凑组成p最多的,就是sum - p最少的,tot - res就是答案
p = sum - p;
int res = INF;
for(int i = 0; i < 2; ++i)
{
for(int j = 0; j < 2; ++j)
{
init2();
int tem = p;
if(i && b[4])
{
--b[4];
tem -= 50;
}
if(j && b[7])
{
--b[7];
tem -= 500;
}
if(tem < 0)
continue;
// cout << "res = " << res << endl;
res = min(res, solve(tem) + i + j);
}
}
printf("%d\n", (res == INF ? -1 : tot - res));
}
return 0;
}
Donate comment here
0%