• 盒子 贪心


    题目:

    盒子
    (box.cpp/in/out 1s 256M)
    小D在玩堆盒子的游戏,每个盒子有一个强度,代表它上方最多能堆多少个
    盒子。由于盒子都是一样大的,所以不能在一个盒子上并列放超过一个盒子。
    现在小D有n个盒子,第i个盒子的强度为xi。小D想知道,如果他要把这些盒
    子全部堆起来,至少要堆多少堆。
    Input
    第一行读入一个整数n,代表小D有的盒子个数。
    第二行读入n个整数,第i个整数xi表示第i个盒子的强度。
    Output
    一个整数表示小D至少要堆多少堆。
    n≤500000,xi≤1000000000。
    Sample Input
    5
    0 2 1 1 2
    Sample Output
    2

    法一:

    此题用小根堆来维护。

    将所有盒子从小到大排序。然后一个个加,这时不再关心盒子本身的那个所谓堆数的限制
    拿样例来说,0 1 1 2 2
    将0这个盒子放到堆中,记值为1代表有一个大小为一个盒子的盒子堆再看数字1,值大于等于目前,所以可以加到这个盒子堆中,盒子堆的体积变2对于第三个数字1,其已不能放到第一堆的盒子堆中了,于是另开一堆出来。其中Heap中有两个元素,一个为1,一个为2,对于第四个数字2,显然可以放到第二堆的盒子堆中。。。

    初始push值为1,因为无论怎样第一个(必须从小到大排序) 一定可以为1堆,若枚举的值大于等于目前堆顶元素,就加入此堆,否则就另开一个堆另一个堆顶元素肯定也为1因为此时另一个堆也有一个元素。

    code:

     1 #include<bits/stdc++.h>
     2 #pragma GCC optimize(3)
     3 const int N=5e5+10;
     4 using namespace std;
     5 int n,a[N];
     6 int ans=1;
     7 priority_queue< int,vector<int>,greater<int> >q; 
     8 inline int read(){
     9     int x=0,f=1;char ch=getchar();
    10     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    11     while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    12     return x*f;
    13 }
    14 inline void write(int x){
    15      char F[200];
    16      int tmp=x>0?x:-x ;
    17      if(x<0)putchar('-') ;
    18      int cnt=0 ;
    19         while(tmp>0)
    20         {
    21             F[cnt++]=tmp%10+'0';
    22             tmp/=10;
    23         }
    24         while(cnt>0)putchar(F[--cnt]) ;
    25 }
    26 int main()
    27 {
    28     n=read();
    29     for(int i=1;i<=n;i++){
    30         a[i]=read();
    31     }
    32     sort(a+1,a+n+1);
    33     q.push(1);
    34     for(int i=2;i<=n;i++){
    35         int x=q.top();
    36         if(x<=a[i]){
    37             q.pop();
    38             x++;
    39             q.push(x);
    40         }
    41         else{
    42             ans++;
    43             q.push(1);
    44         }
    45     }
    46     printf("%d
    ",ans);
    47     return 0;
    48 }

     法二:

    直接两个for循环查找,方法同样类似

    找大于等于当前值

    若小于当前值就再开一堆,即ans++

    code:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n,ans,sum,maxn;
     4 int a[500001];
     5 bool flag[500001];
     6 int main()
     7 {
     8     cin>>n;
     9     for(int i=1;i<=n;i++)
    10         cin>>a[i];
    11     sort(a+1,a+n+1);
    12     maxn=a[n];
    13     for(int i=1;i<=n;i++)
    14         if(!flag[i])
    15         {
    16             ans++;
    17             sum=0;  
    18             for(int k=i;k<=n;k++)
    19                 if(!flag[k]&&a[k]>=sum)
    20                 {
    21                     sum++;
    22                     flag[k]=true;
    23                     if(sum>maxn)break;
    24                 }   
    25         }
    26     cout<<ans;
    27     return 0;
    28 }  
  • 相关阅读:
    如何运用领域驱动设计
    如何运用领域驱动设计
    linq Select与SelectMany的区别
    linq GroupBy 多字段分组
    Enumerable<T>的GroupJoin 方法和Join的用法和区别
    使用vscode搭建vue开发环境
    C# Windows服务发布生成步骤
    C#使用表驱动算法实现多层if或者switch语句重构
    记一次服务器重启后应用程序启动出错
    项目中的NLog日志记录
  • 原文地址:https://www.cnblogs.com/nlyzl/p/11674374.html
Copyright © 2020-2023  润新知