Allowance
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 3887 | Accepted: 1563 |
Description
As a reward for record milk production, Farmer John has decided to start paying Bessie the cow a small weekly allowance. FJ has a set of coins in N (1 <= N <= 20) different denominations, where each denomination of coin evenly divides the next-larger denomination (e.g., 1 cent coins, 5 cent coins, 10 cent coins, and 50 cent coins).Using the given set of coins, he would like to pay Bessie at least some given amount of money C (1 <= C <= 100,000,000) every week.Please help him ompute the maximum number of weeks he can pay Bessie.
Input
* Line 1: Two space-separated integers: N and C
* Lines 2..N+1: Each line corresponds to a denomination of coin and contains two integers: the value V (1 <= V <= 100,000,000) of the denomination, and the number of coins B (1 <= B <= 1,000,000) of this denomation in Farmer John's possession.
* Lines 2..N+1: Each line corresponds to a denomination of coin and contains two integers: the value V (1 <= V <= 100,000,000) of the denomination, and the number of coins B (1 <= B <= 1,000,000) of this denomation in Farmer John's possession.
Output
* Line 1: A single integer that is the number of weeks Farmer John can pay Bessie at least C allowance
Sample Input
3 6 10 1 1 100 5 120
Sample Output
111
Hint
INPUT DETAILS:
FJ would like to pay Bessie 6 cents per week. He has 100 1-cent coins,120 5-cent coins, and 1 10-cent coin.
OUTPUT DETAILS:
FJ can overpay Bessie with the one 10-cent coin for 1 week, then pay Bessie two 5-cent coins for 10 weeks and then pay Bessie one 1-cent coin and one 5-cent coin for 100 weeks.
FJ would like to pay Bessie 6 cents per week. He has 100 1-cent coins,120 5-cent coins, and 1 10-cent coin.
OUTPUT DETAILS:
FJ can overpay Bessie with the one 10-cent coin for 1 week, then pay Bessie two 5-cent coins for 10 weeks and then pay Bessie one 1-cent coin and one 5-cent coin for 100 weeks.
题意:
农夫约翰决定给奶牛贝西津贴,每周至少给C元。
他有N种硬币,硬币的面值从小到大排列,一个是下一个更大值的约数。
告诉你每种硬币的面值、数量,请问农夫约翰最多可以坚持给多少周。
硬币不能拆,每周只能多给不能少,这个题我倒是挺有感觉的,
但是当时一直都不知道要怎么把多种硬币凑一起,很伤,后来看了一些题解,才渐渐明白过来,还是自己这种类型的数学基础不太好
将硬币从小到大排序,从后往前扫描,那种直接能支付的大硬币就直接支付了。
对于小硬币,我们一次一次地凑,先从大往小凑,看一周的剩余价值中最多可以使用多少这种硬币,并记录(而且要减去已经凑好的)
然后如果还没凑够,就从小向大一个一个地加上,看能不能达到,如果能就记录并开始下一轮的凑,
如果不能就退出(此时一定再也不能凑出了,请想一想)
Code:
Status | Accepted |
---|---|
Memory | 668kB |
Length | 1790 |
Lang | G++ |
Submitted | 2017-07-14 10:38:06 |
Shared |
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;
const int Max = 20;
struct node{
int p, num;
bool operator < (const node & X) const{
return p < X.p;
}
}Coin[Max + 5];
int N, C;
int Usenow[Max + 5];
bool getint(int & num){
char c; int flg = 1; num = 0;
while((c = getchar()) < '0' || c > '9'){
if(c == '-') flg = -1;
if(c == -1) return 0;
}
while(c >= '0' && c <= '9'){
num = num * 10 + c - 48;
if((c = getchar()) == -1) return 0;
}
num *= flg;
return 1;
}
/*
int Find(int lft, int r){
int l = 1, mid, rt = 0;
while(l <= r){
mid = (l + r) >> 1;
if(Coin[mid].p >= lft)
rt = mid, r = mid - 1;
else l = mid + 1;
}
return rt;
}*/
int main(){
while(getint(N) && getint(C)){
for(int i = 1; i <= N; ++ i)
getint(Coin[i].p), getint(Coin[i].num);
sort(Coin + 1, Coin + 1 + N);
int Ans = 0;
for(; N >= 1 && Coin[N].p >= C; Ans += Coin[N].num, -- N);
while(1){
int lft = C, num;
for(int i = N; i >= 1; -- i){
num = min(Coin[i].num, lft / Coin[i].p);
lft -= num * Coin[i].p;
Usenow[i] = num;
}
if(lft > 0){//only one coin (not one kind of coin)
for(int i = 1; i <= N; ++ i) if(Coin[i].num && lft - Coin[i].p <= 0){
++ Usenow[i];
lft -= Coin[i].p;
break;
}
}
if(lft > 0) break;
else {
int tmp = 0x3f3f3f3f;
for(int i = 1; i <= N; ++ i) if(Usenow[i])
tmp = min(tmp, Coin[i].num / Usenow[i]);
Ans += tmp;
for(int i = 1; i <= N; ++ i) if(Usenow[i])
Coin[i].num -= tmp * Usenow[i], Usenow[i] = 0;
}
}
printf("%d\n", Ans);
}
return 0;
}