牛客月賽 樂團派對(dp)
阿新 • • 發佈:2020-08-23
題目描述
音樂是帶給大家快樂的存在,而你的目標就是組建若干支樂隊,讓世界聽到你們的演奏!
你目前有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;
}