JZOJ 3792. 【NOIP2014模拟8.20】分队问题

目录:


题目:

单击查看题目


分析:

这道题目,很多dalao都说用dp,但小编觉得贪心也是OK的:
1)我们得先明白怎么选是最优的,那我们只要遇到 a [ i ] 是1的就直接单独建组.
2)我们可以先跑一遍快排,按照每个 a [ i ] 往后选择,如果遇到 a [ i ] 等于1或不够 a [ i ] 时,我们就把这个i放到上个组里


代码(贪心):

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define LL long long
using namespace std;
inline LL read() {
    LL d=0,f=1;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
    return d*f;
}
int x[1000001],ans=0;
int main()
{     
    int n=read();
    for(int i=1;i<=n;i++) x[i]=read();
    sort(x+1,x+1+n);
    int a;
    int i=n,tf;
    while(i>0)
    {
        a=x[i];
        i-=a;
        if(a==1) {ans++;continue;}
        if(i<0) i+=a-1;
        else 
        {
            tf=0;
            for(int j=i+1;j<=i+a;j++)
              if(x[j]==1) tf++;
            if(tf==0) ans++;
            else i+=tf;
        }
    }
    printf("%d",ans);
    return 0;
}

代码(dp):

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
using namespace std;
int a[1000001],n,f[1000001],fmax[1000001];
int main ()
{
    scanf ("%d",&n);
    for (int b=1;b<=n;++b)scanf ("%d",&a[b]);
    sort(a+1,a+n+1);
    for (int b=1;b<=n;++b)
    {
        if (b>=a[b])f[b]=fmax[b-a[b]]+1;
        else f[b]=0;
        fmax[b]=max(f[b],fmax[b-1]);
    }
    printf ("%d",f[n]);
    return 0;
}

转载至洛谷大佬 T i m o t h y


猜你喜欢

转载自blog.csdn.net/qq_35786326/article/details/80988437