poj 2709 Painter

题目翻译:
杂货店出售一种由 N(3<=N<=12)种不同颜色的颜料,每种一瓶(50ML),
组成的颜料套装。你现在需要使用这 N 种颜料;不但如此,你还需要一定
数量的灰色颜料。杂货店从来不出售灰色颜料——也就是它不属于这 N 种
之一。幸运的是,灰色颜料是比较好配置的,如果你取出三种不同颜色的
颜料各 x ml,混合起来就可以得到 xml 的灰色颜料(注意不是 3x)。
现在,你知道每种颜料各需要多少 ml。你决定买尽可能少的“颜料套装”,
来满足你需要的这 N+1 种颜料。那么你最少需要买多少个套装呢?

输入包含若干组测试数据。每组数据一行:第一个数 N, 3<=N<=12, 含
义如上;接下来 N+1 个数,分别表示你需要的 N+1 种颜料的毫升数。
最后一种是灰色。所有输入的毫升数<=1000.

做法是: 先把每种颜料买好,再来制作灰色颜料,我们每次选颜料最多的三种,一个一个的制作灰色颜料,这样得到的答案是最优的,那么实现方法可以有两种,一个是用sort排序,一个是用优先队列。

sort版:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
int a[50];
int main()
{
    int n,f1;
    while(scanf("%d",&n)!=0)
    {
        if(n == 0)
        break;
        int maxn  = 0,ans=0,f1=0;
        for(int i = 1; i <= n; i ++)
        {
            scanf("%d",&a[i]);
            maxn = max(maxn,a[i]);
        }
        cin>>a[n+1];
        if((maxn%50) == 0)
        {
            f1 = maxn/50;
        }
        else f1 = maxn/50+1;
        for(int i = 1; i <= n; i ++)
        {
            a[i] = (f1*50-a[i]);
            q.push(a[i]);
        }
        sort(a+1,a+n+1);
        while(a[n+1] > 0)
        {
            while(a[n-2] > 0)
            {
                a[n]--;
                a[n-1]--;
                a[n-2]--;
                a[n+1]--;
                sort(a+1,a+n+1);
            }
            for(int i = 1; i <= n; i ++)
            {
                a[i] = a[i] + 50;
            }
            if(a[n+1] > 0)
            ans ++;
        }
        printf("%d\n",ans+f1);
    }
    return 0;
}

优先队列版:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
int a[50];
int main()
{
    priority_queue<int>q;
    int n,f1;
    while(scanf("%d",&n)!=0)
    {
        if(n == 0)
        break;
        int maxn  = 0,ans=0,f1=0;
        for(int i = 1; i <= n; i ++)
        {
            scanf("%d",&a[i]);
            maxn = max(maxn,a[i]);
        }
        cin>>a[n+1];
        if((maxn%50) == 0)
        {
            f1 = maxn/50;
        }
        else f1 = maxn/50+1;
        for(int i = 1; i <= n; i ++)
        {
            a[i] = (f1*50-a[i]);
            q.push(a[i]);
        }
        while(a[n+1] > 0)
        {
            int x = q.top();
            q.pop();
            int x1 = q.top();
            q.pop();
            int x2 = q.top();
            q.pop();
            while(x2 > 0)
            {
                x--;x1--;x2--;
                a[n+1]--;
                q.push(x);
                q.push(x1);
                q.push(x2);
                x = q.top();q.pop();
                x1 = q.top();q.pop();
                x2 = q.top();q.pop();
            }
            q.push(x);
            q.push(x1);
            q.push(x2);
            for(int i = 1; i <= n; i ++)
            {
                int y = q.top();
                a[i] = y+50;
                q.pop();
            }
            for(int i = 1; i <= n; i ++)
            q.push(a[i]);
            if(a[n+1] > 0)
            ans ++;
        }
        printf("%d\n",ans+f1);
        while(!q.empty())
        q.pop();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值