n*n匹马和n赛道,求前k名问题

这个问题的非一般形式在网上有很多的分析,比如http://blog.youkuaiyun.com/hackbuteer1/article/details/7481342http://liuyangxdgs.blog.163.com/blog/static/2913776320111056839612/。下面将这个问题一般化,进一步分析这类问题的规律,找出一般性的解法。

问题描述:一共有n*n匹马,有一个赛场,赛场有n个赛道,就是说最多同时可以有n匹马一起比赛。假设每匹马都跑的很稳定,不用任何其他工具,只通过马与马之间的比赛,试问最少得比多少场才能找出跑得最快的k匹马。

设f(n,k)表示n*n匹马,n个赛道,要找出前k名所需要比赛的场数。

当k = 1时,即要找出最快的那匹马。很简单,把所有马分成n组,每组各赛一次,选出每组第一名再赛一次,得到的第一名就是最快的马,f(n,k) = n + 1。

当k > 1 && k <= n时,同样将所有马分成n组,g[1], g[2],...,g[n], 每组比赛一次,得到每个组内的排名。不妨设第 i 组的排名就是g[i][1] > g[i][2] > g[i][3] > ... > g[i][n] (实力从强到弱)。再将各组第一名选出来赛一场,不妨设比赛结果为g[1][1] > g[2][1] > g[3][1] > ... > g[n][1],那么g[1][1]即为第1名。

强    ------->   弱

 |   g1: 1 2 3 4 ... n

 |   g2: 1 2 3 4 ... n

 |   ...

弱  gn: 1 2 3 4 ... n

第2名只能从g[1][2],g[2][1]中选。如果第2名是g[1][2],那第3名就要从g[1][3],g[2][1]中选;如果第2名是g[2][1],那第3名就要从g[1][2],g[2][2],g[3][1]中选,这种情况下需要比赛的马更多。一般地,如果第i名(i >= 1 && i <= k)选出的是g[i][1]时,选第i+1名就需要从g[1][2], g[2][2], g[i][2], g[i+1][1]中选,这种情况下选出一个名次所需要参赛的马最多,选第i+1名就需要i+1匹马参赛。于是选第2名,第3名,第4名,...,第k名所需的最多参赛马匹数为2,3,4,...,k。选第2到第k名所需要安排的比赛场数就相当于将质量为2,3,4, ..., k的球放入最大承重为n的桶中,要求按顺序放入,最少需要的桶的个数。比如,k=5, n=5,球重量为2,3,4,5,那么2,3放入一个桶,4,5各放一个桶,需要3个桶。将质量为2到k的球放入承重为n的桶中所需的最少桶数记为w(n,k),那么 f(n,k) = n + 1 + w(n,k);

当k > n时,每选出一个大于n的名次,就需要n匹马比赛一次,比赛场次数加1。那么 f(n,k) = n + 1 + w(n,n) + k - n;

所以,如果k = 1, f(n,k) = n + 1

        如果k>1 && k <= n, f(n,k) = n + 1 + w(n,k)

        如果k>n, f(n,k) = n + 1 + w(n,k) + k - n

应用:36匹马,6赛道,找出前6名需要的比赛场次为f(6,6) = 6 + 1 + w(6,6)。w(6,6)为将2,3,4,5,6依次放入容量为6的桶需要的最少桶数4。最少需要11场比赛。

 

转载于:https://www.cnblogs.com/segeon/archive/2012/09/16/2687560.html

这是一个经典的算法题,目的是在有限的比赛次数下找到最快的四匹马。我们有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) ``` 此代码片段仅作为示意用途,在真实场景下还需要补充更多细节才能达到理想效果。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值