【codeforces388A】贪心

Fox Ciel has n boxes in her room. They have the same size and weight, but they might have different strength. The i-th box can hold at most xi boxes on its top (we’ll call xi the strength of the box).

Since all the boxes have the same size, Ciel cannot put more than one box directly on the top of some box. For example, imagine Ciel has three boxes: the first has strength 2, the second has strength 1 and the third has strength 1. She cannot put the second and the third box simultaneously directly on the top of the first one. But she can put the second box directly on the top of the first one, and then the third box directly on the top of the second one. We will call such a construction of boxes a pile.

Fox Ciel wants to construct piles from all the boxes. Each pile will contain some boxes from top to bottom, and there cannot be more than xi boxes on the top of i-th box. What is the minimal number of piles she needs to construct?

Input
The first line contains an integer n (1 ≤ n ≤ 100). The next line contains n integers x1, x2, …, xn (0 ≤ xi ≤ 100).

Output
Output a single integer — the minimal possible number of piles.
这里写图片描述
Examples
input
3
0 0 10
output
2
input
5
0 1 2 3 4
output
1
input
4
0 0 0 0
output
4
input
9
0 1 0 2 0 1 1 2 10
output
3

题意:

给出n个箱子,每个箱子都有一个力量值Xi,代表上面能放Xi个箱子,求能把这些箱子摆成的最少的堆数.
(刚开始以为题目是 能放强度是Xi的箱子,看了半天也没看出样例的意思 一看见英文题就头疼)

我的写法:(15ms)

从1开始暴力堆数。最底层是Xi最大的。
include <bits/stdc++.h>
using namespace std;
int a[105],b[105];
bool cmp(int x,int y)
{
    return x>y;
}
int main()
{
    int t, i, n, j;
    cin>>n;
    for(i=1; i<=n; i++)
    {
        scanf("%d", &a[i]);
    }
    sort(a+1,a+1+n,cmp);
    for(t=1;; t++)
    {
        memset(b,-1,sizeof(b));
        bool flag=0;
        for(i=1,j=1; i<=n; i++)
        {
            if(b[j]==0)//b[j]代表上面能放几个箱子,如果0个但是没放完说明假设的这个堆数不成立
            {
                flag=1;
                break;
            }
            if(i<=t)
                b[j]=a[i];//最低层全部放上
            else
                b[j]=min(a[i],b[j]-1);//放上Xi小的
            j++;
            if(j==t+1) j=1;
        }
        if(flag==0)
            break;
    }
    cout<<t<<endl;
    return 0;
}
还在网上搜了贪心写法,具体思路是按小到大排序(不能从大到小排,因为最底层一定要是大的Xi),然后开始循环,放到堆的下面,循环一次堆数加一,最后把所有的箱子放完了看有几堆,具体见注释。
include<bits/stdc++.h>
using namespace std;
int a[105],c[105];
int main()
{
    int n, i, max1=0;
    cin>>n;
    for(i=1; i<=n; i++)
    {
        scanf("%d",&a[i]);
        c[a[i]]++;//记录每个数字出现的次数
        max1=max(max1,a[i]);
    }
    sort(a+1,a+1+n);
    int ans=0,Count;
    while(n)
    {
        Count=0;//每堆此时的数量
        for(i=0; i<=max1; i++)//i是strength
        {
            ///如果有strength为i的箱子没放 并且 可以放到这堆的最下面
            while(c[i]>0&&Count<=i)
            {
                Count++;
                n--;
                c[i]--;
            }
        }
        ans++;//堆数++
    }
    cout<<ans<<endl;
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值