首页 > 技术文章 > 【POJ - 3040】Allowance(贪心)

sky-stars 2019-06-20 11:08 原文

Allowance

原文是English,这里就放Chinese了

Descriptions:

作为创纪录的牛奶生产的奖励,农场主约翰决定开始给Bessie奶牛一个小的每周津贴。FJ有一套硬币N种(1≤N≤20)不同的面额,每枚硬币是所有比他小的硬币面值的倍数,例如1美分硬币、5美分硬币、10美分硬币和50美分硬币。使用这些硬币,FJ每周至少给Bessie C(1 <= C <=100000000)美分。请你计算他最多能给Bessie几周
 
Input
* 第一行N 、 C 
* 第 2..N+1行: 硬币价值 V (1 <= V <= 100,000,000) 和数量 B (1 <= B <= 1,000,000)
 
Output
* 使用这些硬币,每周至少给C美分的前提下的最多周数
 
Sample Input
3 6
10 1
1 100
5 120
Sample Output
111
Hint

输出提示 
FJ给Bessie 10美分一周;给Bessie 5美分和1美分一百周;给Bessie 两枚5美分十周

题目链接:
https://vjudge.net/problem/POJ-3040

 

题目大意:FJ要发硬币工资给他的奶牛,工资不低于c,他有n个硬币,币值和数目。问你最多发多少个星期

 

1)从大面值到小面值一次拿钱,能拿多少拿多少。

但是注意不能拿到的钱的总和大于C

2)如果第一步拿到的钱不够C,那么就从小面值到大面值拿钱,能拿多少拿多少。

直到拿到的钱总和大于等于C

 

AC代码

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#define mod 1000000007
#define eps 1e-6
#define ll long long
#define INF 0x3f3f3f3f
#define ME0(x) memset(x,0,sizeof(x))
using namespace std;
pair<int,int> a[25];//硬币面值,数量
int use[25];//这个面值的硬币已经使用了多少
int n,c;//硬币种类,每周最少给多少钱
int main()
{
    cin>>n>>c;
    for(int i=1; i<=n; i++)
        cin>>a[i].first>>a[i].second;
    sort(a+1,a+1+n);
    int ans=0;//答案
    while(true)
    {
        ME0(use);//每次都归零
        int rest=c;//还有这么多钱没给奶牛
        for(int i=n; i>=1; i--)//从大到小
        {
            int tmp=min(rest/a[i].first,a[i].second);//这种类型的硬币能拿几个
            rest-=tmp*a[i].first;//还有多少钱没给奶牛
            use[i]=tmp;//这种硬币用了几个
        }
        if(rest)//还有钱没有发完
        {
            for(int i=1; i<=n; i++)//从小到大
            {
                if(a[i].second&&a[i].first>=rest)//这种硬币没有花完并且这种硬币的价值大于没有发完的钱
                {
                    use[i]++;//这种硬币用了一个
                    rest=0;//钱全部发给奶牛了
                    break;
                }
            }
        }
        if(rest)//钱还没发完,即钱不够了,退出循环
            break;
        int minx=INF;
        for(int i=1; i<=n; i++)//从小到大
        {
            if(use[i])//这种硬币一周要用几个,可以算出剩余的硬币可以用多少周
                minx=min(minx,a[i].second/use[i]);
        }
        ans+=minx;
        for(int i=1; i<=n; i++)//把硬币的数量更新
        {
            if(use[i])
                a[i].second-=use[i]*minx;
        }
    }
    cout<<ans<<endl;
}

 

推荐阅读