Codeforces Round #544 (Div. 3) E. K Balanced Teams (DP)
-
题意:有\(n\)个人,每个人的能力值是\(a_i\),现在你想将这些人分成\(k\)组(没必要全选),但是每组中最高水平和最低水平的人的能力差值必须\(\le 5\),问最多能选多少人.
-
题解:想了一会发现纯贪心写不了,必须要用dp来求解,先排序,我们记\(dp[i,j]\),表示前\(i\)个人分成\(j\)组选的最多的人数,当便遍历到某个人的时候,他可以不加任何组\(dp[i][j]=dp[i-1][j]\),否则如果他要加入,那么我们往前找到第一个与其能力差值\(>5\)的位置\(pos\),然后在\([1,pos]\)这些人已经分成\(j-1\)组的情况下将\([pos+1,i]\)这些人分成一组一定是最优的,于是\(dp[i][j]=max(dp[i][j],dp[pos][j-1]+i-pos)\).
-
代码:
int n,k; int a[N]; int dp[5010][5010]; int main() { ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); cin>>n>>k; rep(i,1,n) cin>>a[i]; sort(a+1,a+1+n); dp[1][1]=1; rep(i,1,n){ int las=i; while(a[i]-a[las]<=5 && las>=1) las--; rep(j,1,min(i,k)){ dp[i][j]=dp[i-1][j]; dp[i][j]=max(dp[i][j],dp[las][j-1]+i-las); } } int ans=0; rep(j,1,k) ans=max(ans,dp[n][j]); cout<<ans<<'\n'; return 0; }
𝓐𝓬𝓱𝓲𝓮𝓿𝓮𝓶𝓮𝓷𝓽 𝓹𝓻𝓸𝓿𝓲𝓭𝓮𝓼 𝓽𝓱𝓮 𝓸𝓷𝓵𝔂 𝓻𝓮𝓪𝓵
𝓹𝓵𝓮𝓪𝓼𝓾𝓻𝓮 𝓲𝓷 𝓵𝓲𝓯𝓮