poj 3040 Allowance

Allowance

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 3008   Accepted: 1218

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.

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.

题意:有各种面值的钞票,每种都有若干张,每个星期都要用这些钞票的一部分去支付C元及以上的费用,最终要使得支付的星期尽可能的多,那么最多可以支付多少星期

思路:首先按面值从大到小来排序,若钞票的面值大于等于C,只能一张一张先付掉,之后只剩下比C小的钞票,这些钞票进行各种组合使得sum大于C,具体组合方法:

先按面值从大到小循环,用一个数组来记录各种各种面值的钞票各用了多少张,使得总和sum尽可能接近C且比C小一点;第二步:按面值从小到大循环,继续用上面所述数组来记录各种面值的钞票还需要用多少张,最终使得总和sum超过C,但最多只能超过一点点。

组合出sum之后,看看这种组合最多能有几组。之后再进行下一次新的组合……直到所有的组合都用完了,结束。

AC代码:

#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<algorithm>
using namespace std;
const int V_MAX = 20;
struct money {
    int V;
    int num;
    bool operator <(const money&b) {
        return V > b.V;
    }
};
money mon[V_MAX];
int need[V_MAX];
int main() {
    int N, C;
    while (cin >> N >> C) {
        int week = 0;
        for (int i = 0;i < N;i++) {
            scanf("%d%d", &mon[i].V, &mon[i].num);
            if (mon[i].V >= C) {
                week += mon[i].num;//面值大于C的钱只能一张一星期的给
                mon[i].num = 0;
            }
        }
        sort(mon,mon+N);//按面值从大到小排
        while (1) {//每一次循环将产生一种能超过sum的钞票组合
            int sum = C;//每一种组合要凑足sum
            memset(need, 0, sizeof(need));
            for (int i = 0;i < N;i++) {//面值从大到小
                if(sum > 0&&mon[i].num) {
                    int can_use = min(mon[i].num,sum/mon[i].V);//当前面值的钞票的最多能拿几张,尽量多,但不能超过sum
                    if (can_use>0) {
                        sum -= can_use*mon[i].V;
                        need[i] = can_use;
                    }
                }
            }
            for (int i = N - 1;i >= 0;i--) {//面值从小到大
                if (sum > 0 && mon[i].num) {
                    int can_use = min(mon[i].num-need[i],(sum+mon[i].V-1)/mon[i].V);//当前面值的钞票尽量多拿,但超过sum一点点就可以了,不要浪费
                    if (can_use>0) {
                        sum -= can_use*mon[i].V;
                        need[i] += can_use;
                    }
                }
            }

            if (sum > 0) {
                break;
            }
            //至此拼凑出sum需要各种面值的钞票的数量已经都存放在need[]数组中了
            int add = INT_MAX;
            for (int i = 0;i < N;i++) {
                if (need[i] == 0)continue;
                 add= min(add, mon[i].num / need[i]);//当前的拼凑出sum的组合最多能有几组
            }
            week += add;
            for (int i = 0;i < N;i++) {//将该组合所使用掉的钞票去除
                if (need[i] == 0)continue;
                mon[i].num -= need[i] * add;
            }

        }
        cout << week << endl;
    }
    return 0;
}
时间: 2024-12-21 11:12:49

poj 3040 Allowance的相关文章

Allowance (poj 3040 贪心)

Language: Default Allowance Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1728   Accepted: 718 Description As a reward for record milk production, Farmer John has decided to start paying Bessie the cow a small weekly allowance. FJ has

挑战程序设计竞赛2.2习题:Allowance POJ - 3040

Allowance 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

POJ 3040 贪心

链接: http://poj.org/problem?id=3040 题解: 1:大于c的就直接取: 2:如果小于就从大到小拿钱,能拿多少拿多少,但不能超过c: 3:如果2拿的钱小于c,就从小到大拿钱,能拿多少拿多少,但要求是超过c的时候是最小的,也就是说,这些钱的总和是大于c的最小数: 4:将此类取钱方式求出次数,加到ans中,然后返回第二步. 代码: 1 #include <map> 2 #include <set> 3 #include <cmath> 4 #in

[2017.9.9]Problem

POJ - 1328  Radar Installation        POJ - 3253  Fence Repair    POJ - 3662  Telephone Lines           POJ - 3616  Milking Time                POJ - 3666  Making the Grade        POJ - 3040  Allowance                   POJ - 3181  Dollar Dayz       

2019.3.29

贪心:一直超时,查了后发现要标记. 不过sun和v不写>0会出错? http://poj.org/problem?id=3040 1 #include<iostream> 2 #include<cmath> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define N 15000 7 #define ll long long 8 #define inf 0x3f

[SinGuLaRiTy] 贪心题目复习

[SinGuLaRiTy-1024] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. [POJ 2709] 颜料 (Painter) 题目描述 杂货店出售一种由N(3<=N<=12)种不同颜色的颜料,每种一瓶(50ML),组成的颜料套装.你现在需要使用这N种颜料:不但如此,你还需要一定数量的灰色颜料.杂货店从来不出售灰色颜料——也就是它不属于这N种之一.幸运的是,灰色颜料是比较好配置的,如果你取出三种不同颜色的颜料各x ml,混合起来就

《挑战程序设计竞赛》学习笔记 (1)

2.2 贪心法 贪心法是遵循某种规则,不断贪心选取当前最优策略的算法设计方法. 贪心法的求解思想是通过迭代地选取当前问题的局部最优解法来达成总体最优解,在迭代的过程中不断地产生局部最优解和下一个与之前问题同构的子问题. 贪心法所处理的问题总是具有最优子结构的性质:该问题的最优解包含子问题的最优解. 使用贪心法处理的时候如何选取贪心策略非常关键,选定正确的策略往往要求一定的洞察力,验证贪心策略的正确性可能使用数学归纳法或者反证法. 与搜索和动规不同,贪心法的特点是解决问题的顺序是固定的,而且不能回

每日训练任务 红色表示未完成

7.21 POJ 1328 POJ 3040 模拟乘法 除法 看到别人搞的java 和 py 挖草 怎么别人那么强啊 7.22 贪心C //需要好好想清楚一些 7-24 多重部分和 , dp入门 ,抓紧思考 7-26 感觉自己怎么这么没有耐心学一些新的知识呢...GG...先看看小白? dp入门 E,F,G,H,I,J,K,L,M

POJ - 3186 Treats for the Cows (区间DP)

题目链接:http://poj.org/problem?id=3186 题意:给定一组序列,取n次,每次可以取序列最前面的数或最后面的数,第n次出来就乘n,然后求和的最大值. 题解:用dp[i][j]表示i~j区间和的最大值,然后根据这个状态可以从删前和删后转移过来,推出状态转移方程: dp[i][j]=max(dp[i+1][j]+value[i]*k,dp[i][j-1]+value[j]*k) 1 #include <iostream> 2 #include <algorithm&