题目
Allowance
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 2611 | Accepted: 1069 |
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的直接支付一天,无需考虑。
对于小于C的情况,先选择大的货币,但是不超出C,如果正好(left=0)那就直接计算最大支付天数(canpayday)然后按照比例减去货币。
如果没凑齐,(left>0)那么从面值小的向大的方向凑齐,这个过程中如果凑齐了那就计算canpayday,按比例减去.
如果还没凑齐,那基本上就是没有货币了。break掉。
大概思路就是这样,下面贴代码
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
struct cash
{
int value;
int amount;
};
bool cmp(const cash& a,const cash& b)
{
return a.value<b.value;
}
int need[64];
int makedayfrom(vector<cash>& vec,int C)
{
memset(need,0,sizeof(int)*64);
int N=vec.size();
int left=C;
for(int i=N-1;i>=0;i--)
{//
if(vec.at(i).amount>0&&left>0)
{
int x=left/vec.at(i).value;
x=min(x,vec.at(i).amount);
need[i]=x;
left-=x*vec.at(i).value;
}
}
if(left>0)
{
for(int i=0;i<N;i++)
{
if(vec.at(i).amount>need[i]&&left>0)
{
int x=left/vec.at(i).value;
if(x==0)
{
/// try to make x = 1
need[i]++;
left=0;
break;
}
}
}
}
if(left>0)
{
return -1;
}
int canpayday=2<<29;
for(int i=0;i<64;i++)
{
if(need[i]>0)
{
canpayday=min(canpayday,vec.at(i).amount/need[i]);
}
}
if(canpayday<=0) return -1;
for(int i=0;i<N;i++)
{
if(need[i]>0)
{
vec.at(i).amount-=canpayday*need[i];
}
}
return canpayday;
}
int main()
{
int N,C;
scanf("%d %d",&N,&C);
vector<cash> vec;
int ans=0;
for(int i=0;i<N;i++)
{
cash s;
scanf("%d %d",&s.value,&s.amount);
vec.push_back(s);
}
sort(vec.begin(),vec.end(),cmp);
for(int i=N-1;i>=0;i--)
{
if(vec.at(i).value>=C)
{
ans+=vec.at(i).amount;
vec.pop_back();
}
else break;
}
int tmp;
while((tmp=makedayfrom(vec,C))>0)
{
ans+=tmp;
}
printf("%d\n",ans);
return 0;
}
中间还参考了一些别的代码,直接上链接:
我在GitHub上建立了一个仓库,用于存放已经AC的题目的源代码。如果各位有未收录的题目或者有更好的解法,欢迎fork仓库+PR~ 让我们共同创建一个AC代码集中仓库,造福ACM Beginner ~
仓库地址: OJ-Problems-Source On GitHub