华为OD机试题库《C++》限时优惠 9.9
华为OD机试题库《Python》限时优惠 9.9
华为OD机试题库《JavaScript》限时优惠 9.9
针对刷题难,效率慢,我们提供一对一算法辅导, 针对个人情况定制化的提高计划(全称1V1效率更高)A
看不懂有疑问需要答疑辅导欢迎私VX: code5bug
游戏里面,队伍通过匹配实力相近的对手进行对战。但是如果匹配的队伍实例相差太大,对于双方游戏体验都不会太好。
给定n个队伍的实力值,对其进行两两实力匹配,两支队伍实例差距在允许的最大差距d内,则可以匹配。
要求在匹配队伍最多的情况下,匹配出的各组实力差距的总和最小。
第一行,n,d。队伍个数n。允许的最大实力差距d。(2<=n<=50,0<=d<=100)。
第二行,n个队伍的实力值,空格分割。(0<=各队伍实力值<=100)。
匹配后,各组对战的实力差值的总和。若没有队伍可以四配,则输出-1。
输入:
6 30
81 87 47 59 81 18
输出:
57
说明:
18与47配对,实力差距29;
59与81配对,实力差距22;
81与87配对,实力差距6。
总实力差距29+22+6=57。
输入:
6 20
81 87 47 59 81 18
输出:
12
说明:
最多能匹配成功4支队伍。
47与59配对,实力差距12;
81与81配对,实力差距0。
总实力差距12+0=12。
输入:
4 10
40 51 62 73
输出:
-1
说明:
实力差距都在10以上,没有队伍可以匹配成功。
这道题目属于贪心算法(Greedy Algorithm)和动态规划(Dynamic Programming)的结合。我们需要在满足匹配条件的情况下,最大化匹配数量并最小化实力差距总和。类似的问题在力扣上通常归类为区间调度或二分图匹配问题。
解题思路
- 排序:首先将队伍的实力值排序,以便后续匹配时能快速找到满足条件的队伍。
- 贪心匹配:从最小的实力值开始,尝试与最近的满足条件的队伍匹配。这样可以保证在匹配数量最多的情况下,实力差距总和最小。
- 动态规划:使用递归或记忆化搜索来记录已匹配的队伍,避免重复匹配,并确保在每一步选择最优解。
// 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;
}
整理题解不易, 如果有帮助到您,请给点个赞 ❤️ 和收藏 ⭐,让更多的人看到。