64匹马,8个赛道。找出前4名最少比赛多少场(概率分析+验证代码)

博客围绕赛马比赛确定前四的场次展开分析。先将马分8组各跑一次,再取每组第一名比赛,筛选出可能的前四马匹。分需明确前四顺序和不必明确顺序两种情况,分别给出比赛安排及所需场次的概率,并给出Python代码印证分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先上结论:
如果需要明确前四的顺序:有92/93(约为98.92%)的概率只需要十场比赛,1/93(约为1.08%)的概率需要进行第十一场。
如果不必明确前四的顺序:有5654/5673(约为99.67%)的概率只需要十场,19/5673(约为0.33%)的概率需要进行第十一场。

第一步:全部马分8组,各跑一次(共8次)
第二步:取每组第一名进行一次比赛(共1次)

分析:
1、按照第二步(每组第一名)比赛结果的名次,对各组进行排序,即:第一名所在组为A组,第二名所在组为B组,以此类推
2、每一组根据第一步比赛结果进行排序,如A组第一名为A1,第二名为A2,以此类推
3、E、F、G、H这四组不可能有前四(因为已经有A1、B1、C1、D1比它们快)
4、每一组的5号以后不可能是前四(因为同一组前四名比它们快)
5、D2不可能是前四,因为有A1、B1、C1、D1比它快,以此类推,D3、D4、C3、C4、B4不可能是前四
6、A1是最快的

综上,A1已经晋级,只需要从A2、A3、A4、B1、B2、B3、C1、C2、D1中取前三,就能得到前四
马有九匹,赛道只有八条,要怎样安排第十场?这是需要讲究的事情。安排好了,可以最大限度地避免进行第十一场。
第三步:取A2、A3、B1、B2、B3、C1、C2、D1进行一次比赛(共1次)
结果分两种:
A、如果前三名按从快到慢顺序为A2、A3、B1,那么还不知道A4和B1谁快,需要进行一次加赛,A2、A3、A4、B1取前三(附加1次)
B、其他情况,则A1+前三名为前4名

结论:按照以上安排,有92/93(约为98.92%)的概率只需要十场比赛,1/93(约为1.08%)的概率需要进行第十一场。
以下是 python 代码。运行结果印证了以上分析。


import random

class Horse:
    def __init__(self):
        self.reset()

    def reset(self):
        self.counter = 0
        self.values = []
        for x in range(64):
            self.values.append(random.randint(1000,9999)*100+x)

    def check_best(self, indexes):
        best = self.best()
        for x in range(4):
            if indexes[x] != best[x]:
                return False
        return True

    def count(self):
        return self.counter

    def best(self):
        return sorted(range(64), key=lambda x: self.values[x], reverse=True)[0:4]

    def sort(self, indexes):
        self.counter = self.counter + 1
        return sorted(indexes, key=lambda x: self.values[x], reverse=True)

    def get(self, indexes):
        return [(x, self.values[x]) for x in indexes]


def get_best(horse):
    values = [horse.sort([k + x*8 for k in range(8)]) for x in range(8)]
    index = [x // 8 for x in horse.sort([n[0] for n in values])]
    serial = [values[x] for x in index]
    second = [serial[y][x] for x in range(4) for y in range(4-x)]
    best = [second[0]]
    items = horse.sort(second[1:9])[0:3]
    if serial[1][0] == items[2]:
        items.append(serial[0][3])
        items = horse.sort(items)[0:3]
    best.extend(items)
    return best


if __name__ == '__main__':
    rept = 100000
    horse = Horse()
    count = 0
    for x in range(rept):
        horse.reset()
        best = get_best(horse)
        count = count + horse.count()
        if not horse.check_best(best):
            print(f'ERR :{horse.get(best)}')
            print(f'best:{horse.get(horse.best())}')
    print(f'average: {count/rept}')

注:reset 里的 random.randint(1000,9999)*100+x 是为了让每个值都不相同。当然也可以用 range(64) 再进行洗牌。

--------------------------------------------------------------------------------
如果只要找出前四,不必整理出顺序,第三步也可以:
第三步:取A2、A3、A4、B2、B3、C1、C2、D1进行一次比赛(共1次)
结果分两种:
A、前三为A2、A3、A4。那么还不知道B1是不是更快,需要进行一次加赛,A2、A3、A4、B1取前三(附加1次)
B、其他情况,必然包含B2或C1,它们都比B1慢,所以,只要取A1、B1和第十轮的前两名,即为前四(这种情况无法确定二、三、四名的顺序)
这种情况的概率为:有5654/5673(约为99.67%)的概率只需要十场,19/5673(约为0.33%)的概率需要进行第十一场。
Python 代码如下。运行结果印证了以上分析。


import random

class Horse:
    def __init__(self):
        self.reset()

    def reset(self):
        self.counter = 0
        self.values = []
        for x in range(64):
            self.values.append(random.randint(1000,9999)*100+x)

    def check_best(self, indexes):
        best = self.best()
        for x in range(4):
            if indexes[x] != best[x]:
                return False
        return True

    def count(self):
        return self.counter

    def best(self):
        return sorted(range(64), key=lambda x: self.values[x], reverse=True)[0:4]

    def sort(self, indexes):
        self.counter = self.counter + 1
        return sorted(indexes, key=lambda x: self.values[x], reverse=True)

    def get(self, indexes):
        return [(x, self.values[x]) for x in indexes]


def get_best(horse):
    values = [horse.sort([k + x*8 for k in range(8)]) for x in range(8)]
    index = [x // 8 for x in horse.sort([n[0] for n in values])]
    serial = [values[x] for x in index]
    second = [serial[y][x] for x in range(4) for y in range(4-x)]
    best = [second[0]]
    second[1], second[9] = second[9], second[1]
    items = horse.sort(second[1:9])[0:3]
    if serial[0][3] == items[2]:
        items.append(serial[1][0])
        items = horse.sort(items)[0:3]
    else:
        items = [serial[1][0], items[0], items[1]]
    best.extend(items)
    return best


if __name__ == '__main__':
    rept = 100000
    horse = Horse()
    count = 0
    for x in range(rept):
        horse.reset()
        best = get_best(horse)
        count = count + horse.count()
        best = horse.sort(best)
        if not horse.check_best(best):
            print(f'ERR :{horse.get(best)}')
            print(f'best:{horse.get(horse.best())}')
    print(f'average: {count/rept}')

注:以校验前多了一行 best = horse.sort(best),是因为前四的顺序没有明确,所以在校验前要先对结果进行排序。

概率计算公式:

 

(可以鼓掌了)

这是一个经典的算法题,目的是在有限的比赛次数下找到最快的四匹马。我们有64匹马、8赛道,并且每次只能赛完一组后再安排下一组比赛。下面我们逐步分析最优解法。 --- ### 分析与解答 #### 第一步:初步筛选 将所有马分成 **8 组**(每组 8 匹),分别进行比赛。 这需要 **8比赛**。赛后记录每组的排情况。 此时我们可以得到每个小组内的相对快慢顺序,但不知道跨组的具体速度关系。 #### 第二步:确定“最快的一批” 从第一步中选出各组的第一共 **8 匹马** 进行第9比赛。这比赛会给出整体最快速度的排序所在的初始范围。 例如: - 若 `A1 > B1 > C1 > D1 ...` 表示 A 组第一胜过其他组第一,则说明 A 组第一可能是全局第一。 - 同理推导出第二至第四可能来自哪些组合。 注意:只有部分几组里的列才有机会进入最终候选单! #### 第三步:缩小范围再次竞争 基于上述结果进一步减少参赛者数量。因为已经明确某些组别不可能贡献额外更快成员了,所以可以直接排除掉那些无关紧要的个体。接下来只需再组织少数关键选手间最后一轮较量即可得出确切结论。 假设最后发现只需要比较约20余匹左右潜在优胜者,则设计新一轮合理赛事数目不会超过5左右。 综上所述总共不超过 **14 比赛** 就能锁定答案。 --- ### Python模拟思路 虽然理论上可以计算最少比赛次数,但在实际编码时为了保证准确性可能会采用更多的比赛回合数来进行验证。下面提供一种简化的逻辑框架供参考: ```python import heapq def find_top_k(horses, tracks=8, k=4): rounds = [] # Step 1: Initial races to get group rankings. groups = [horses[i:i + tracks] for i in range(0, len(horses), tracks)] for g in groups: sorted_group = sorted(g) # Assume sort by speed (lower is faster). rounds.append(sorted_group) # Step 2: Race the winners of each initial race. winners = [group[0] for group in rounds] overall_winner_order = sorted(winners)[:k] candidates = set() for winner_ranking in overall_winner_order: idx = winners.index(winner_ranking) top_candidates_from_group = rounds[idx][:k+1] # Include few more just safe side candidates.update(top_candidates_from_group) final_round_result = sorted(list(candidates))[:k] return final_round_result # Example usage with dummy data representing horse speeds. dummy_horses = list(range(64)) # Lower number means faster here. top_4_fastest = find_top_k(dummy_horses, tracks=8, k=4) print("Top 4 fastest horses:", top_4_fastest) ``` 此代码片段仅作为示意用途,在真实景下还需要补充更多细节才能达到理想效果。 ---
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值