poj 2709 painter 贪心 2017.10.10 模拟赛

题目描述
杂货店出售一种由 N(3<=N<=12)种不同颜色的颜料,每种一瓶(50ML),组成的颜料套装。你现在需要使用这 N 种颜料;不但如此,你还需要一定数量的灰色颜料。杂货店从来不出售灰色颜料——也就是它不属于这 N 种之一。幸运的是,灰色颜料是比较好配置的,如果你取出三种不同颜色的颜料各 x ml,混合起来就可以得到 xml 的灰色颜料(注意不是 3x)。
现在,你知道每种颜料各需要多少 ml。你决定买尽可能少的“颜料套装”,来满足你需要的这 N+1 种颜料。那么你最少需要买多少个套装呢?
输入描述
输入包含若干组测试数据。每组数据一行:第一个数 N, 3<=N<=12, 含义如上;接下来 N+1 个数,分别表示你需要的 N+1 种颜料的毫升数。最后一种是灰色。所有输入的毫升数<=1000.
注意:输入中不存在每个颜料套装的毫升数。由题意可知,每种各 50ml,
即一共 50N ml
输出描述
每组数据输出一行,最少需要的套装数。
样例输入
3 40 95 21 0
7 25 60 400 250 0 60 0 500
4 90 95 75 95 10
5 0 0 0 0 0 333
0
样例输出
2
8
2
4
数据范围及提示
对于 30%的数据 N=3
对于 100%的数据 3 <= N <= 100
数据最多不超过 10 组

/*由题意可知,我们得到灰色的前提是要有其他颜色,
我们也需要其他颜色,而且其他颜色可直接得到,所以,
为方便计算,我们先不考虑灰色,只求满足其他颜色时所需要购买的套装数。
看样例就可以知道,颜料不一定都用上,那么剩下的就用来制造灰色颜料。
因为我们的最终目的是买尽可能少的套装来满足我们所需要的颜料数,
所以用到贪心的思想,将剩下的颜料排序,每次取最大的三个,
如果刚好能造出所需要的灰色颜料那就不用买了,
但是,若果不满足呢?刚开始写的时候是让 所需要的灰-min(最大的三个),
但是会减出负数呀,如果每次减出负数就加一套,想想就觉得浪费了其他的颜料,
**所以**,我们取出最大的来后,每次灰-1,直到灰减到0
(//(前三个中有=0的,不得不买一套,因为后面剩余的颜料一定全为0)
//a[2]或a[3]为0,则a[1]一定为0,∴不考虑),
后面的剩下的少的颜料也有用到的机会,最大限度利用剩余颜料

//用优先队列也可以,自己就不用再排序

考试时还总结出了4种情况,想多了。。。。。。*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=15;
int a[maxn],b[maxn];

bool cmp(int a,int b)
{
    return a>b;
}

int main()
{
    freopen("painter.in", "r", stdin);
    freopen("painter.out", "w", stdout);
    int n,m,k;
    while(scanf("%d",&n)&&n)//正常输入n且n不等于0 
    {
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        scanf("%d",&m);
        sort(a,a+n);
        if(a[n-1]%50==0) k=a[n-1]/50;
        else k=a[n-1]/50+1;
        int t=0;
        for(int i=0;i<n;i++)
            b[i]=k*50-a[i];
        while(t<m)
        {
            if(b[2]==0)
            {
                k+=1;
                for(int i=0;i<n;i++)
                    b[i]+=50;
            }
            else
            {
                t++;
                b[0]--,b[1]--,b[2]--;
                sort(b,b+n,cmp);
            }
        }
        cout<<k<<endl;
    }
    return 0;
}


//不新开一个b[]
//sort
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

int n;
int a[30];

bool cmp(int x,int y)
{
    return x>y;
}

int main()
{
    freopen("painter.in","r",stdin);
    freopen("painter.out","w",stdout);

    int ans=0,hui;
    while(scanf("%d",&n)&&n)
    {
        if(n==0) break;
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        scanf("%d",&hui);
        sort(a+1,a+n+1,cmp);
        ans=a[1]/50+1;
        if(a[1]%50==0) ans--;
        for(int i=1;i<=n;i++) a[i]=50*ans-a[i];
        //不要写成a[i]-50*ans,多余的=已经买了的颜料-原来有的颜料
        sort(a+1,a+n+1,cmp);
        while(hui!=0)
        {
            if(a[2]==0||a[3]==0||a[2]==0&&a[3]==0)
            {
                ans++;
                for(int i=1;i<=n;i++) a[i]+=50;
            }
            else
            {
                a[1]--;
                a[2]--;
                a[3]--;
                hui--;
                sort(a+1,a+n+1,cmp);
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值