Skip to content

14207: 【原4207】大主教带队

题目

题目描述

author: RayCiel 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/4207

Description

大主教管n名ACM班小朋友,第i名小朋友的编程技能是\(a_i\)。

老板想要为一个新的编程比赛组成k个团队。众所周知,更多的小朋友参与竞争,胜利可能性更大。因此大主教必须安排不超过k个(至少一个)的非空队伍,这样小朋友的总数才能最大化。但大主教也知道每个队伍都应该保持平衡。这意味着每个队伍的每对小朋友的编程技能应该相差不超过5。队伍是相互独立的(这意味着两个来自不同队伍的小朋友在编程技能上的差异并不重要)。

有可能有些小朋友根本没有被纳入任何团队。

大主教的任务是报告不超过k个(至少一个)非空平衡团队中可能的最大小朋友总数。

Input Format

输入的第一行包含两个整数n和k\((1 \leq k \leq n \leq 5000)\)对应的是小朋友人数和最大队伍数。

输入的第二行包含n个整数\(a_1,a_2,…,a_n(1 \leq a_i \leq 10^9)\),其中\(a_i\)是第i个学生的编程技能。

Output Format

一个整数——不超过k(至少一个)的非空平衡队伍中小朋友总数的最大值

Sample Input

5 2
1 2 15 15 15

Sample Output

5

ligongzzz's solution

#include "iostream"
#include "cstdio"
using namespace std;

int a[5009] = { 0 };

template <class T, class T_val = decltype(*declval<T>()),
    class Compare = bool (*)(T_val, T_val)>
    void quick_sort(T start, T end,
        Compare cmp = [](T_val a, T_val b) {return a < b; }) {
    if (start == end)
        return;
    auto i = start, j = end;
    --j;
    if (i == j)
        return;
    //交换
    auto key = *start;
    for (bool status = true; i != j;) {
        if (status) {
            if (cmp(*j, key)) {
                *i = *j;
                ++i;
                status = false;
            }
            else
                --j;
        }
        else {
            if (cmp(key, *i)) {
                *j = *i;
                --j;
                status = true;
            }
            else
                ++i;
        }
    }
    *i = key;
    //递归
    quick_sort(start, ++i, cmp);
    quick_sort(i, end, cmp);
}

int dp_data[5000][5000] = { 0 };
int n;

int dp(int pos, int k) {
    if (pos >= n || k <= 0) {
        return 0;
    }
    if (dp_data[pos][k] > 0)
        return dp_data[pos][k];
    int ans1 = dp(pos + 1, k), ans2 = 0, i = pos;
    for (; i < n; ++i) {
        if (a[i] - a[pos] <= 5)
            ++ans2;
        else
            break;
    }
    ans2 += dp(i, k - 1);
    dp_data[pos][k] = ans1 < ans2 ? ans2 : ans1;
    return dp_data[pos][k];
}

int main() {
    int k;
    cin >> n >> k;

    for (int i = 0; i < n; ++i)
        scanf("%d", &a[i]);

    quick_sort(a, a + n);

    cout << dp(0, k);

    return 0;
}

skyzh's solution

#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;

struct Range {
    Range(int L, int R) : L(L), R(R) {}
    int L, R;
    friend bool operator< (const Range& a, const Range& b) {
        if ((a.R - a.L) == (b.R - b.L)) return a.L < b.L;
        return (a.R - a.L) < (b.R - b.L);
    }
};

int main() {
    priority_queue <Range, vector<Range>, less<Range> > t;
    int n, k;
    int cap[10000] = { 0 };
    cin >> n >> k;
    for (int i = 0; i < n; i++) cin >> cap[i];
    sort(cap, cap + n);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j <= i; j++) {
            if (cap[i] - cap[j] <= 5) {
                t.push(Range(j, i));
            }
        }
    }
    bool visited[10000] = { 0 };
    while (!t.empty() && k > 0) {
        Range r = t.top();
        bool found = true;
        for (int i = r.L; i <= r.R; i++) {
            if (visited[i]) {
                found = false;
                break;
            }
        }
        if (found) {
            for (int i = r.L; i <= r.R; i++) {
                visited[i] = true;
            }
            --k;
        }
        t.pop();
    }
    int sum = 0;
    for (int i = 0; i < n; i++) if (visited[i]) ++sum;
    cout << sum << endl;
    return 0;
}