Too Rich
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 1613 Accepted Submission(s): 413
Problem Description
You are a rich person, and you think your wallet is too heavy and full now. So you want to give me some money by buying a lovely pusheen sticker which costs
p
dollars from me. To make your wallet lighter, you decide to pay exactly
p
dollars by as many coins and/or banknotes as possible.
For example, if p=17 and you have two $10 coins, four $5 coins, and eight $1 coins, you will pay it by two $5 coins and seven $1 coins. But this task is incredibly hard since you are too rich and the sticker is too expensive and pusheen is too lovely, please write a program to calculate the best solution.
For example, if p=17 and you have two $10 coins, four $5 coins, and eight $1 coins, you will pay it by two $5 coins and seven $1 coins. But this task is incredibly hard since you are too rich and the sticker is too expensive and pusheen is too lovely, please write a program to calculate the best solution.
Input
The first line contains an integer
T
indicating the total number of test cases. Each test case is a line with 11 integers
p,c1,c5,c10,c20,c50,c100,c200,c500,c1000,c2000
, specifying the price of the pusheen sticker, and the number of coins and banknotes in each denomination. The number
ci
means how many coins/banknotes in denominations of
i
dollars in your wallet.
1≤T≤20000
0≤p≤109
0≤ci≤100000
1≤T≤20000
0≤p≤109
0≤ci≤100000
Output
For each test case, please output the maximum number of coins and/or banknotes he can pay for exactly
p
dollars in a line. If you cannot pay for exactly
p
dollars, please simply output '-1'.
Sample Input
3 17 8 4 2 0 0 0 0 0 0 0 100 99 0 0 0 0 0 0 0 0 0 2015 9 8 7 6 5 4 3 2 1 0
Sample Output
9 -1 36
Source
题意:给若干个不同面值硬币,求凑成指定面额的最多硬币数量。
思路:比较巧妙地搜素,首先题目可以转化为拿走最少的硬币使得剩下硬币总额满足要求。那么按照贪心肯定是从面值最大的先拿,为什么这里直接贪心会正确呢?留意到题目给的面值前面的恰好是后面的因子,也就是说,大面值的能拿就拿走,否则还要小面值的凑成它,比如能拿50就拿50,否则以后还要拿5个10凑成50。还有一个问题,20不是50的因子,200不是500的因子,但是20却是50+50的因子,200却是500+500的因子,这意味着拿50和500的时候,还要考虑拿少一个硬币的情况,给20或200的硬币留空间,否则将会漏掉情况,如20,20,20,50凑60块这种数据。
# include <iostream>
# include <cstdio>
# include <cstring>
using namespace std;
typedef long long LL;
const LL INF = 0x3f3f3f3f3f3f3f3f;
LL a[]={0,1,5,10,20,50,100,200,500,1000,2000}, b[13];
LL ans;
void dfs(int cur, LL tot, LL cnt)
{
if(tot < 0) return;
if(cur == 0)
{
if(tot == 0)
ans = min(ans, cnt);
return;
}
LL tmp = min((LL)b[cur], tot/a[cur]);
dfs(cur-1, tot-tmp*a[cur], cnt+tmp);
if(tmp) dfs(cur-1, tot-(tmp-1)*a[cur], cnt+tmp-1);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
LL tot = 0, sum = 0, all = 0; ans = INF;
scanf("%lld",&sum);
for(int i=1; i<=10; ++i) scanf("%lld",&b[i]), tot += a[i]*b[i], all += b[i];
if(tot < sum)
{
puts("-1");
continue;
}
dfs(10, tot-sum, 0);
if(ans == INF) puts("-1");
else
printf("%lld\n",all-ans);
}
return 0;
}