bzoj2386 [CEOI2011] Team

题意

给你n个数,每个数的大小在1到n之间,要求把它们分成几组,每个数字的大小要小于等于它所在组中的数字总个数,问最多能分出多少组.

分析

首先把所有数字排序,比较显然的是最后一定存在一个最优解是按这个顺序把所有数字划分为若干个区间,一个区间一组.(如果不是,一定可以进行恰当的交换使得是若干区间)
然后...我写了个错误的贪心...每次从后往前分组,分每一组的时候尽量少选人...然而这样不一定最优,例如 1 1 3 3 3 3,按这个贪心策略会分出{1,1,3},{3,3,3},最优解是{1},{1},{3,3,3,3}
你们看这就是菜鸡
应该DP,F[i]表示把前i个人分为若干组的最多组数,然后f[i]=max(f[0],f[1]...f[i-a[i])+1

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=1000005;
int a[maxn];
int w[maxn];
int f[maxn],g[maxn];
int main(){
  int n;scanf("%d",&n);
  for(int i=1;i<=n;++i)scanf("%d",&a[i]),w[a[i]]++;
  int cnt=0;
  for(int i=1;i<=n;++i){
    while(w[i]--){
      a[++cnt]=i;
    }
  }
  f[0]=g[0]=0;
  for(int i=1;i<=n;++i){
    if(i>=a[i])f[i]=g[i-a[i]]+1;
    g[i]=max(g[i-1],f[i]);
  }
  printf("%d\n",f[n]);
  return 0;
}

posted @ 2017-06-14 16:06  liu_runda  阅读(262)  评论(2编辑  收藏  举报
偶然想到可以用这样的字体藏一点想说的话,可是并没有什么想说的. 现在有了:文化课好难