题目描述
音乐是带给大家快乐的存在,而你的目标就是组建若干支乐队,让世界听到你们的演奏!
你目前有n位乐手,每位乐手只能进入一个乐队,但并不是每位乐手都能担大任,因此需要团队合作。第ii位乐手的能力值为a[i]a[i],表示该位乐手所在乐队的人数必须大于等于a[i]。在保证每位乐手都被分进一个乐队的情况下,乐队数量最多可以是多少?
输入描述
第一行一个正整数n,表示乐手人数,n≤1e5。
第二行n个正整数a[i],表示每位乐手的能力值,a[i]≤1e9。
输出描述
输出最多的乐队数量。若无法保证每位乐手都被分进一个乐队,则输出-1。
示例1
输入
4
2 1 2 1
输出
3
思路
贪心的思想是尽可能使a[i]值大的乐手组到一个乐队,按a[i]从小到大排序。构造一个dp数组,dp[i]表示当前人数i所能组成乐队的最大数量。
有转移方程,当i<a[i]时,当前人数构不成乐队,dp[i]=0;当i>=a[i]时,dp[i]=max(dp[i-a[i]],dp[i-a[i]-1,......dp[0])+1;(因为多余的人可以加进本队中,目的是使人数转移到使乐队数最多的人数);
再一边转移一边维护一个前缀max数组,max[i]=max(max[i-1],dp[i]);即当i>=a[i]时,dp[i]=max[dp[i-a[i]]+1;
当dp[n]等于0时,证明无法保证所有人在一个乐队,输出-1。
#include<bits/stdc++.h>
using namespace std;
int a[100005];
int dp[100005];
int maxx[100005];
int main(){
int n;cin>>n;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
sort(a+1,a+n+1);
for(int i=1;i<=n;i++){
if(a[i]>i)dp[i]=0;
else dp[i]=maxx[i-a[i]]+1;
maxx[i]=max(dp[i],maxx[i-1]);
}
if(dp[n]==0){
cout<<"-1"<<endl;
}
else cout<<dp[n]<<endl;
return 0;
}