poj-3040 Allowance

版权声明:最后一年,加油~ https://blog.csdn.net/zzti_xiaowei/article/details/81812557

[题目链接]

思路:
贪心策略是使多发的面额最小(最优解)。分三个阶段:

  • 首先面额不小于C的硬币属于没办法节约的类型,先统统发掉。
  • 然后对硬币面额从大到小尽量凑得接近C,允许等于或不足C,但是不能超出C。
  • 接着按硬币面额从小到大凑满C(凑满的意思是允许超出一个最小面值,ps此处的最小面值指的是硬币剩余量不为0的那些硬币中的最小面值),凑满之后得出了最优解,发掉,进入步骤2.

并没有很明白,也没有证出来~,只是有点感觉orz~~~

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int n,c;
struct node {
    int v,b;
    bool operator<(const node& n)const {
        return v<n.v;
    }
}no[33];

int main() 
{
    scanf("%d%d",&n,&c);
    for(int i=0;i<n;i++)scanf("%d%d",&no[i].v,&no[i].b);
    int sum=0;
    sort(no,no+n);
    n--;
    while(n>=0&&no[n].v>=c){
        sum+=no[n].b;
        no[n].b=0;
        n--;
    } 
    while(true){
        int t=0;
        for(int i=n;i>=0;i--){
            while(no[i].b>0&&t+no[i].v<=c){
                t+=no[i].v;
                no[i].b--;
            }
        }
        for(int i=0;i<=n;i++){
            while(no[i].b>0&&t<c){
                t+=no[i].v;
                no[i].b--;
            }
            if(t>=c){sum++;break;}
        }
        if(t<c)break;
    }
    printf("%d",sum);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zzti_xiaowei/article/details/81812557