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

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

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

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

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

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

华为OD机试真题

题目描述

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

给定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. 动态规划:使用递归或记忆化搜索来记录已匹配的队伍,避免重复匹配,并确保在每一步选择最优解。

Python

from functools import cache

def main():
    n, d = map(int, input().split())
    power = list(map(int, input().split()))
    power.sort()  # 升序排序

    @cache
    def dfs(i):
        if i >= n:
            return (0, 0)

        # 不选当前队伍
        cnt1, diff1 = dfs(i + 1)

        # 选当前队伍和下一个满足条件的队伍
        cnt2, diff2 = 0, 0
        if i + 1 < n and power[i + 1] - power[i] <= d:
            cnt2, diff2 = dfs(i + 2)
            cnt2 += 1
            diff2 += power[i + 1] - power[i]

        # 优先匹配数多的方案,其次选总差值小的
        if cnt2 > cnt1:
            return (cnt2, diff2)
        elif cnt1 > cnt2:
            return (cnt1, diff1)
        else:
            return (cnt1, min(diff1, diff2))

    total_cnt, total_diff = dfs(0)
    print(total_diff if total_cnt > 0 else -1)


if __name__ == "__main__":
    main()

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

什码情况

你的鼓励就是我最大的动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值