poj 3040 深入理解贪心思想

来源:互联网 发布:全金属开放式网络桥架 编辑:程序博客网 时间:2024/05/18 02:21
Allowance

Time Limit: 1000MS


Memory Limit: 65536K

Total Submissions: 2300


Accepted: 945

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 610 11 1005 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元,约翰有n种面值的钱币,第i种的面值为v_i,数量有b_i。问这些钱最多给贝西发多少天的工资。注意,每种面值的金钱都是下一种的面值的倍数。

首先 排序 价值比 c大的肯定都是不能节约的。把这些面值的数目都加上去。
然后  从大到小填充c,但是不能超过c。
最后用小面值来填充剩余部分,直接大过c,从而保证浪费最小。

这里有两个关键,我感觉也是我做了一些贪心题目发现的一个特点。
最接近最小和刚好大过最小跳出的操作。
最接近最小但是不能大过最小,用除法向下取整,刚好大于最小就用排序的数和数目限制,刚好达到就退出。

从局部的最优解找出总体最优解。 别人的题解,写得很好,我马克一下


#include <string>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>


using namespace std;
int use[30];
#define INF 0x3f3f3f


struct node
{
    int v,b;
}a[25];


int cmp(node a,node b)
{
    return a.v<b.v;
}


int main()
{
    int n,c,i,cnt,ans,k,m;
    while(scanf("%d%d",&n,&c)!=EOF)
    {
        for(i=0;i<n;i++)
        {
            scanf("%d%d",&a[i].v,&a[i].b);
        }
        sort(a,a+n,cmp);
        ans=0;
        for(i=n-1;i>=0;i--)
        {
            if(a[i].v>=c)
            {
                ans+=a[i].b;
                a[i].b=0;
            }
        }
while(1)
{
int sign=0;
cnt=c;
memset(use,0,sizeof(use));
for(i=n-1;i>=0;--i)
{
if(a[i].b)
{
k=cnt/a[i].v;
m=min(k,a[i].b);
cnt-=m*a[i].v;
use[i]=m;
if(cnt==0)
{
sign=1;
break;
}
}
}
if(cnt>0)
{
for(i=0;i<n;i++)
{
if(a[i].b>use[i])
{
while(use[i]<a[i].b)
{
cnt-=a[i].v;
use[i]++;
if(cnt<=0)
{
sign=1;
break;
}
}
}
if(sign)
 break;
}
}
if(!sign)
{
break;
}
m=INF;
for(i=0;i<n;i++)
{
if(use[i])
m=min(m,a[i].b/use[i]);
}
ans+=m;
for(i=0;i<n;i++)
{
if(use[i])
a[i].b-=m*use[i];
}
}
printf("%d\n", ans);
}
}

0 0
原创粉丝点击