64匹马,8个赛道,找出前4名最少比赛多少场?

64匹马,8个赛道,找出前4名最少比赛多少场?
第一步:全部马分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是最快的

64匹马,8个赛道,找出前4名最少比赛多少场?


综上,A1已经晋级,只需要从A2、A3、A4、B1、B2、B3、C1、C2、D1中取前三,就能得到前四
怎样安排第十场需要讲究了,安排好了,可以不必进行第十一场。
第三步:取A2、A3、B1、B2、B3、C1、C2、D1进行一次比赛(1次)
结果分两种:
如果前三名为A2、A3、B1,那么还不知道A4和B1谁快,就要进行一次加赛,A2、A3、A4、B1取前三
其他情况,则A1+前三名为最前4名
结论:按照以上安排,有92/93的机率只要十场比赛,1/93的机率要进行十一场。

以下是 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 go(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)
    if not horse.check_best(best):
        print(f'ERR :{horse.get(best)}')
        print(f'best:{horse.get(horse.best())}')
    return horse.count()


if __name__ == '__main__':
    rept = 100000
    horse = Horse()
    count = 0
    for x in range(rept):
        horse.reset()
        count = count + go(horse)
    print(f'average: {count/rept}')


注:

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

2、第三步也可以取A2、A3、A4、B2、B3、C1、C2、D1进行比赛,结果相同,当前三是A2、A3、A4时需要A2、A3、A4、B1进行第十一场,也是1/93的机率。

 

(可以鼓掌了)

上一篇:[CF1358D] The Best Vacation - 双指针


下一篇:连续邮资问题