n个数,分组,数Ai要在至少含有Ai个数的组,求最多分多少组。
方法一:大的数应该尽量跟大的在一起,这样才能让小的出现很多很多组,所以从大到小排序,给当前序列中最大的数x分x个数。代码如下:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<algorithm> 5 //#include<iostream> 6 using namespace std; 7 8 int n; 9 #define maxn 1000011 10 int a[maxn]; 11 bool cmp(const int &a,const int &b) {return a>b;} 12 int main() 13 { 14 scanf("%d",&n); 15 for (int i=1;i<=n;i++) scanf("%d",&a[i]); 16 sort(a+1,a+1+n,cmp); 17 int ans=0,i; 18 for (i=1;i<=n;i+=a[i]) ans++; 19 if (i>n+1) ans--; 20 printf("%d ",ans); 21 return 0; 22 }
错误!“最大的数尽量跟大的在一起”不等于"给最大的数x分x个数“,有时一个大数可以多容纳一点大数来满足更多的小数组。有反例(TJM大爷提供)1 1 1 3 3 3 3,答案4,错误答案3。
方法二:贪心不行就dp。先把数从小到大排序,f[i]--前i个数分组最多,f[i]=max(f[j])+1,j∈[1,i-a[i]],重复地访问前缀最大可另开数组统计。
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<algorithm> 5 //#include<iostream> 6 using namespace std; 7 8 int n; 9 #define maxn 1000011 10 int a[maxn],f[maxn],Max[maxn]; 11 int main() 12 { 13 scanf("%d",&n); 14 for (int i=1;i<=n;i++) scanf("%d",&a[i]); 15 sort(a+1,a+1+n); 16 f[0]=Max[0]=0; 17 for (int i=1;i<=n;i++) 18 { 19 if (i-a[i]>=0) 20 f[i]=Max[i-a[i]]+1; 21 else f[i]=0; 22 Max[i]=max(Max[i-1],f[i]); 23 } 24 printf("%d ",f[n]); 25 return 0; 26 }