cf Codeforces Round #544 E. K Balanced Teams

原题:

E. K Balanced Teams
time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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,问你最多能有多少个数被分到组中。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
 
typedef pair<int,int> pii;
const int maxn = 5001;
 
int a[maxn];
pii seg[maxn];
int dp[maxn][maxn];
int link[maxn];
 
int n,k;
 
int main()
{
    ios::sync_with_stdio(false);
 
    while(cin>>n>>k)
    {
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
        }
        sort(a+1,a+1+n);
 
        for(int i=1;i<=n;i++)
        {
            int j=i-1;
            seg[i].second=seg[i].first=i;
            while(true)
            {
                if(j==0)
                {
                    seg[i].first=1;
                    break;
                }
                if(a[i]-a[j]<=5)
                {
                    seg[i].first=j;
                    j--;
                }
                else
                {
                    seg[i].first=j+1;
                    break;
                }
            }
        }
        for(int i=1;i<=n;i++)
        {
            int j=i-1;
            link[i]=i;
            while(true)
            {
                if(j==0)
                {
                    link[i]=0;
                    break;
                }
                if(seg[i].first>seg[j].second)
                {
                    link[i]=j;
                    break;
                }
                else
                {
                    j--;
                }
            }
        }
      
 
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=k;j++)
            {
               p[link[i]][j-1]+seg[i].second-seg[i].first+1<<" ";
                if(j<=i)
                {
                    dp[i][j]=max(dp[i][j],dp[i-1][j]);//
                    dp[i][j]=max(dp[i][j],dp[link[i]][j-1]+seg[i].second-seg[i].first+1);
                }
                else
                    dp[i][j]=dp[i][j-1];
            }
        }
        cout<<dp[n][k]<<endl;
 
    }
    return 0;
}

思路:

先排序,然后对每一个数a找到它后面距离a最远的数b,且满足b-a<=5,将a和b作为一个区间,segiseg_i,同时设置linkilink_i记录第i个数作为区间右端点时,索引到左端点的位置。
问题转换成求找出k个区间尽量覆盖n个数。

典型的n选k最优问题,使用动态规划方法,设置状态dp[i][j]表示前i个数使用j个区间最多能覆盖多少个数,状态转移方程有。

dp[i][j]=max(dp[i][j],dp[i1][j],dp[link[i]][j1]+seg[i].secondseg[i].first+1)dp[i][j]=max(dp[i][j],dp[i-1][j],dp[link[i]][j-1]+seg[i].second-seg[i].first+1)

max函数中后面两项的表示两个状态,分别为第i个区间不加入任何一个小组时,前i-1个数分成j组的最优值;以及,第i个区间加入小组时,link[i]之前的区间组成j-1个小组时的最优值,加上第i个区间得到的结果

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章