codeforces1133E.K Balanced Teams

本文介绍了一种算法,旨在解决将具备不同编程技能的学生合理分配到若干团队中的问题。目标是确保每个团队内部成员的技能差距不超过5,同时尽可能多地容纳学生。通过排序、双指针技术和动态规划来实现这一目标。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

You are a coach at your local university. There are n students under your supervision, the programming skill of the i-th student is ai.
You have to form k teams for yet another new programming competition. As you know, the more students are involved in competition the more probable the victory of your university is! So you have to form no more than k (and at least one) non-empty teams so that the total number of students in them is maximized. But you also know that each team should be balanced. It means that the programming skill of each pair of students in each team should differ by no more than 5. Teams are independent from one another (it means that the difference between programming skills of two students from two different teams does not matter).
It is possible that some students not be included in any team at all.
Your task is to report the maximum possible total number of students in no more than k(and at least one) non-empty balanced teams.
If you are Python programmer, consider using PyPy instead of Python when you submit your code.

Input
The first line of the input contains two integers n
and k (1≤k≤n≤5000) — the number of students and the maximum number of teams, correspondingly.
The second line of the input contains n
integers a1,a2,…,an (1≤ai≤109), where ai is a programming skill of the i-th student.

Output
Print one integer — the maximum possible total number of students in no more than k(and at least one) non-empty balanced teams.

Examples
Input

5 2
1 2 15 15 15

Output

5

Input

6 1
36 4 1 25 9 16

Output

2

Input

4 4
1 10 100 1000

Output

4

一共有n个人,每个人有一个能力值,要分成不超过k队,每队不限人数,但要求队伍中任意两人的能力值相差不超过5,求最多能有多少人能分到队伍中。
首先,先求出如果第i人为队伍中得最大值时,这个队伍可以有哪些人。排序加双指针,遍历一遍就完事。
预处理之后,进行动态规划的设计。记数组dp[i][j],为前i个人(不包括i),分成j组时,最多有多少人能分到队伍中。之后根据所设计的数组,考虑在第i个人,分成j组时的情况。我们可以选择

  1. 将第i个人为新队伍的最大值新建一只队伍
    假设从第i个人到第k个人可以分到一组,而第k+1个人不能与第i个人一组。因为区间[i,k]之间的已经被拉到一个队伍中,所以若第i个人新开一组,那么应该跳到 第k+1个人分为j+1组时的情况
  2. 第i个人不分组
    跳转到下一个人,即第i+1个人分为j组的情况

综上,有状态转移方程

   dp[i+1][j]=max(dp[i][j],dp[i+1][j]);
   dp[i+N[i]][j+1]=max(dp[i+N[i]][j+1],dp[i][j]+N[i]);

#include <stdio.h>
#include <climits>
#include <cstring>
#include <time.h>
#include <math.h>
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <utility>
#include <vector>
#include <string>

#define INF 0x3f3f3f3f
#define ll long long
#define Pair pair<int,int>
#define re return

#define mem(a,b) memset(a,b,sizeof(a))
#define Make(a,b) make_pair(a,b)
#define Push(num) push_back(num)
#define rep(index,star,finish) for(register int index=star;index<finish;index++)
#define drep(index,finish,star) for(register int index=finish;index>=star;index--)
using namespace std;

int store[5005];
int N[5005],jump[5005];
int dp[5002][5005];
inline bool cmp(const int &a,const int &b);
int main(){
    ios::sync_with_stdio(false);

    int n,k;
    cin>>n>>k;
    rep(i,1,n+1){
        cin>>store[i];
    }
    //Ascending
    sort(store+1,store+n+1,cmp);

    //get map
    mem(N,0);
    int pos=1,point=2;
    while(pos<=n){
        while(point<=n && store[pos]-store[point]<=5)
            point++;
        N[pos]+=point-pos;
        pos++;
    }

    //Dynamic programming
    mem(dp,0);
    rep(i,1,n+1){
        rep(j,0,min(i+1,k+1)){
            dp[i+1][j]=max(dp[i][j],dp[i+1][j]);
            dp[i+N[i]][j+1]=max(dp[i+N[i]][j+1],dp[i][j]+N[i]);
        }
    }

    int ans=INT_MIN;
    rep(i,0,k+1)
        ans=max(ans,dp[n+1][i]);
    cout<<ans<<endl;

    re 0;
}
inline bool cmp(const int &a,const int &b){
    re a>b;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值