POJ_3040 Allowance(greedy)

来源:互联网 发布:美原油软件 编辑:程序博客网 时间:2024/05/16 09:41

题目请点我

题解:

这道题是贪心没错,但是贪心的方法不好想,参考了别人的代码,希望最终自己能有所收获。

贪心思想:

每一次先从大的开始挑,在不超过C的情况下尽可能多的从大往小拿。如果凑不够钱数,在找到一个最小的满足条件的凑数。

贪心原理:

在钱数一定的情况下,我们应该保证每次多给的钱越少越好。所以每次能给大面值就先给大面值,不够的话用小面值补充,这样可以保证最后不会超的很多。

参考博客博主每次设置的need数组很巧妙。

代码实现:

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#define LL long longusing namespace std;const int MAX = 22;const int INF = 0x7fffffff;struct node{    int cost,num;    friend bool operator < (node a,node b){        return a.cost < b.cost;    }};int sum;int N,C;bool flag;int use[MAX];node Lis[MAX];int main(){    scanf("%d%d",&N,&C);    for( int i = 0; i < N; i++ ){        scanf("%d%d",&Lis[i].cost,&Lis[i].num);    }    flag = false;    sort(Lis,Lis+N);    while( 1 ){        memset(use,0,sizeof(use));        int Left = C;        for( int i = N-1; i >= 0; i-- ){            int tmp = Left/Lis[i].cost;            tmp = min(tmp,Lis[i].num);            use[i] += tmp;            Left -= tmp*Lis[i].cost;        }        if( Left > 0 ){            for( int i = 0; i < N; i++ ){                if( Lis[i].num>use[i] && Lis[i].cost>Left ){                    use[i]++;                    Left = 0;                    break;                }            }        }        if( Left > 0 ){            break;        }        int add = INF;        for( int i = 0; i < N; i++ ){            if( use[i] != 0 ){                add = min(add,Lis[i].num/use[i]);            }        }        sum += add;        for( int i = 0; i < N; i++ ){            Lis[i].num -= add*use[i];        }    }    printf("%d\n",sum);    return 0;}


0 0
原创粉丝点击