最佳对手 - 华为OD统一考试(A卷、C++题解)

华为OD机试题库《C++》限时优惠 9.9

华为OD机试题库《Python》限时优惠 9.9

华为OD机试题库《JavaScript》限时优惠 9.9

针对刷题难,效率慢,我们提供一对一算法辅导, 针对个人情况定制化的提高计划(全称1V1效率更高)A

看不懂有疑问需要答疑辅导欢迎私VX: code5bug

最佳对手 - 华为OD统一考试(A卷、C++题解)_第1张图片

题目描述

游戏里面,队伍通过匹配实力相近的对手进行对战。但是如果匹配的队伍实例相差太大,对于双方游戏体验都不会太好。

给定n个队伍的实力值,对其进行两两实力匹配,两支队伍实例差距在允许的最大差距d内,则可以匹配。

要求在匹配队伍最多的情况下,匹配出的各组实力差距的总和最小。

输入描述

第一行,n,d。队伍个数n。允许的最大实力差距d。(2<=n<=50,0<=d<=100)。
第二行,n个队伍的实力值,空格分割。(0<=各队伍实力值<=100)。

输出描述

匹配后,各组对战的实力差值的总和。若没有队伍可以四配,则输出-1。

示例1

输入:
6 30
81 87 47 59 81 18

输出:
57

说明:
18与47配对,实力差距29;
59与81配对,实力差距22;
81与87配对,实力差距6。
总实力差距29+22+6=57。

示例2

输入:
6 20
81 87 47 59 81 18

输出:
12

说明:
最多能匹配成功4支队伍。
47与59配对,实力差距12;
81与81配对,实力差距0。
总实力差距12+0=12。

示例3

输入:
4 10
40 51 62 73

输出:
-1

说明:
实力差距都在10以上,没有队伍可以匹配成功。

题解

这道题目属于贪心算法(Greedy Algorithm)动态规划(Dynamic Programming)的结合。我们需要在满足匹配条件的情况下,最大化匹配数量并最小化实力差距总和。类似的问题在力扣上通常归类为区间调度二分图匹配问题。


解题思路

  1. 排序:首先将队伍的实力值排序,以便后续匹配时能快速找到满足条件的队伍。
  2. 贪心匹配:从最小的实力值开始,尝试与最近的满足条件的队伍匹配。这样可以保证在匹配数量最多的情况下,实力差距总和最小。
  3. 动态规划:使用递归或记忆化搜索来记录已匹配的队伍,避免重复匹配,并确保在每一步选择最优解。

C++

// Author: code5bug
#include 

using namespace std;

pair<int, int> dfs(int i, const vector<int>& power, int d, unordered_map<int, pair<int, int>>& memo) {
    if (memo.count(i)) {
        return memo[i];
    }
    if (i >= power.size()) {
        return {0, 0};
    }

    // 不选当前队伍
    auto skip = dfs(i + 1, power, d, memo);

    // 选当前队伍和下一个满足条件的队伍
    pair<int, int> take = {0, 0};
    if (i + 1 < power.size() && power[i+1] - power[i] <= d) {
        take = dfs(i + 2, power, d, memo);
        take.first++;
        take.second += power[i+1] - power[i];
    }

    // 优先匹配数多的方案,其次选总差值小的
    if (take.first > skip.first) {
        memo[i] = take;
    } else if (skip.first > take.first) {
        memo[i] = skip;
    } else {
        memo[i] = {skip.first, min(skip.second, take.second)};
    }

    return memo[i];
}

int main() {
    int n, d;
    cin >> n >> d;
    vector<int> power(n);
    for (int i = 0; i < n; ++i) {
        cin >> power[i];
    }
    sort(power.begin(), power.end());  // 升序排序

    unordered_map<int, pair<int, int>> memo;
    auto result = dfs(0, power, d, memo);

    if (result.first > 0) {
        cout << result.second << endl;
    } else {
        cout << -1 << endl;
    }

    return 0;
}

整理题解不易, 如果有帮助到您,请给点个赞 ‍❤️‍ 和收藏 ⭐,让更多的人看到。

你可能感兴趣的:(华为od,算法,数据结构,面试,c++)