算法设计比赛做啥算法好

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法设计比赛做啥算法好相关的知识,希望对你有一定的参考价值。

我们学校(本科)有一个算法设计竞赛,请问做什么算法比较好。

应该是ACM吧
就是给你8-10道算法题目,5个小时,做出来多的题目数越多,排名越靠前,如果题目数一样多的看用的时间。
时间的计算方法如下:
例如你A题用了20分钟AC,然后B题有用了30分钟AC(此时是比赛开始50分钟),又用了30分钟AC了C题,那么你的时间(penalty )是
20 + 50 + 80 = 150分钟

比赛中常用的算法有
1。动态规划
2。搜索
3。贪心
4。图论
5。组合数学
6。计算几何
7。数论


推荐到
http://acm.pku.edu.cn
http://acm.zju.edu.cn
http://acm.hdu.edu.cn
http://acm.timus.ru
这几个OJ上练习

比较好的题目分类(POJ上的)
1。这个是我最喜欢的
初期:
一.基本算法:
(1)枚举. (poj1753,poj2965)(2008-10-27Done 位运算+宽搜)
(2)贪心(poj1328,poj2109,poj2586)
(3)递归和分治法.
(4)递推.
(5)构造法.(poj3295)
(6)模拟法.(poj1068,poj2632,poj1573,poj2993,poj2996)
二.图算法:
(1)图的深度优先遍历和广度优先遍历.
(2)最短路径算法(dijkstra,bellman-ford,floyd,heap+dijkstra)(2008-08-29Done)
(poj1860,poj3259,poj1062,poj2253,poj1125,poj2240)
(3)最小生成树算法(prim,kruskal)
(poj1789,poj2485,poj1258,poj3026)
(4)拓扑排序 (poj1094)(2008-09-01Done)
(5)二分图的最大匹配 (匈牙利算法) (poj3041,poj3020)
(6)最大流的增广路算法(KM算法). (poj1459,poj3436)
三.数据结构.
(1)串 (poj1035,poj3080,poj1936)
(2)排序(快排、归并排(与逆序数有关)、堆排) (poj2388,poj2299)
(3)简单并查集的应用.
(4)哈希表和二分查找等高效查找法(数的Hash,串的Hash)
(poj3349,poj3274,POJ2151,poj1840,poj2002,poj2503)
(5)哈夫曼树(poj3253)(2008-09-02Done)
(6)堆
(7)trie树(静态建树、动态建树) (poj2513)(2008-10-23Done 并查集、欧拉)
四.简单搜索
(1)深度优先搜索 (poj2488,poj3083,poj3009,poj1321,poj2251)
(2)广度优先搜索(poj3278,poj1426,poj3126,poj3087.poj3414)
(3)简单搜索技巧和剪枝(poj2531,poj1416,poj2676,1129)
五.动态规划
(1)背包问题. (poj1837,poj1276)
(2)型如下表的简单DP(可参考lrj的书 page149):
1.E[j]=optD+w(i,j) (poj3267,poj1836,poj1260,poj2533)
2.E[i,j]=optD[i-1,j]+xi,D[i,j-1]+yj,D[i-1][j-1]+zij (最长公共子序列)
(poj3176,poj1080,poj1159)
3.C[i,j]=w[i,j]+optC[i,k-1]+C[k,j].(最优二分检索树问题)
六.数学
(1)组合数学:
1.加法原理和乘法原理.
2.排列组合.
3.递推关系.
(POJ3252,poj1850,poj1019,poj1942)
(2)数论.
1.素数与整除问题
2.进制位.
3.同余模运算.
(poj2635, poj3292,poj1845,poj2115)
(3)计算方法.
1.二分法求解单调函数相关知识.(poj3273,poj3258,poj1905,poj3122)
七.计算几何学.
(1)几何公式.
(2)叉积和点积的运用(如线段相交的判定,点到线段的距离等). (poj2031,poj1039)
(3)多边型的简单算法(求面积)和相关判定(点在多边型内,多边型是否相交)
(poj1408,poj1584)
(4)凸包. (poj2187,poj1113)(2008-08-29Done)
中级:
一.基本算法:
(1)C++的标准模版库的应用. (poj3096,poj3007)
(2)较为复杂的模拟题的训练(poj3393,poj1472,poj3371,poj1027,poj2706)
二.图算法:
(1)差分约束系统的建立和求解. (poj1201,poj2983)(2008-09-05Done)
(2)最小费用最大流(poj2516,poj2516,poj2195)
(3)双连通分量(poj2942)
(4)强连通分支及其缩点.(poj2186)
(5)图的割边和割点(poj3352)
(6)最小割模型、网络流规约(poj3308, )
三.数据结构.
(1)线段树. (poj2528,poj2828,poj2777,poj2886,poj2750)
(2)静态二叉检索树. (poj2482,poj2352)
(3)树状树组(poj1195,poj3321)
(4)RMQ. (poj3264,poj3368)
(5)并查集的高级应用. (poj1703,2492)
(6)KMP算法. (poj1961,poj2406)(2008-09-16Done)
四.搜索
(1)最优化剪枝和可行性剪枝
(2)搜索的技巧和优化 (poj3411,poj1724)
(3)记忆化搜索(poj3373,poj1691)

五.动态规划
(1)较为复杂的动态规划(如动态规划解特别的施行商问题等)
(poj1191,poj1054,poj3280,poj2029,poj2948,poj1925,poj3034)
(2)记录状态的动态规划. (POJ3254,poj2411,poj1185)
(3)树型动态规划(poj2057,poj1947,poj2486,poj3140)
六.数学
(1)组合数学:
1.容斥原理.
2.抽屉原理.
3.置换群与Polya定理(poj1286,poj2409,poj3270,poj1026).
4.递推关系和母函数.

(2)数学.
1.高斯消元法(poj2947,poj1487, poj2065,poj1166,poj1222)
2.概率问题. (poj3071,poj3440)
3.GCD、扩展的欧几里德(中国剩余定理) (poj3101)
(3)计算方法.
1.0/1分数规划. (poj2976)
2.三分法求解单峰(单谷)的极值.
3.矩阵法(poj3150,poj3422,poj3070)
4.迭代逼近(poj3301)
(4)随机化算法(poj3318,poj2454)
(5)杂题.
(poj1870,poj3296,poj3286,poj1095)
七.计算几何学.
(1)坐标离散化.
(2)扫描线算法(例如求矩形的面积和周长并,常和线段树或堆一起使用).
(poj1765,poj1177,poj1151,poj3277,poj2280,poj3004)
(3)多边形的内核(半平面交)(poj3130,poj3335)
(4)几何工具的综合应用.(poj1819,poj1066,poj2043,poj3227,poj2165,poj3429)
高级:
一.基本算法要求:
(1)代码快速写成,精简但不失风格
(poj2525,poj1684,poj1421,poj1048,poj2050,poj3306)
(2)保证正确性和高效性. poj3434
二.图算法:
(1)度限制最小生成树和第K最短路. (poj1639)
(2)最短路,最小生成树,二分图,最大流问题的相关理论(主要是模型建立和求解)
(poj3155, poj2112,poj1966,poj3281,poj1087,poj2289,poj3216,poj2446
(3)最优比率生成树. (poj2728)
(4)最小树形图(poj3164)
(5)次小生成树.
(6)无向图、有向图的最小环
三.数据结构.
(1)trie图的建立和应用. (poj2778)(2008-10-26Done 矩阵A^n)
(2)LCA和RMQ问题(LCA(最近公共祖先问题) 有离线算法(并查集+dfs) 和 在线算法
(RMQ+dfs)).(poj1330)
(3)双端队列和它的应用(维护一个单调的队列,常常在动态规划中起到优化状态转移的
目的). (poj2823)
(4)左偏树(可合并堆).
(5)后缀树(非常有用的数据结构,也是赛区考题的热点).
(poj3415,poj3294)
四.搜索
(1)较麻烦的搜索题目训练(poj1069,poj3322,poj1475,poj1924,poj2049,poj3426)

(2)广搜的状态优化:利用M进制数存储状态、转化为串用hash表判重、按位压缩存储状态、双向广搜、A*算法. (poj1768,poj1184,poj1872,poj1324,poj2046,poj1482)
(3)深搜的优化:尽量用位运算、一定要加剪枝、函数参数尽可能少、层数不易过大、可以考虑双向搜索或者是轮换搜索、IDA*算法. (poj3131,poj2870,poj2286)
五.动态规划
(1)需要用数据结构优化的动态规划.
(poj2754,poj3378,poj3017)
(2)四边形不等式理论.
(3)较难的状态DP(poj3133)
六.数学
(1)组合数学.
1.MoBius反演(poj2888,poj2154)
2.偏序关系理论.
(2)博奕论.
1.极大极小过程(poj3317,poj1085)
2.Nim问题.
七.计算几何学.
(1)半平面求交(poj3384,poj2540)
(2)可视图的建立(poj2966)
(3)点集最小圆覆盖.
(4)对踵点(poj2079)
八.综合题.
(poj3109,poj1478,poj1462,poj2729,poj2048,poj3336,poj3315,poj2148,poj1263)

2。这个每个分类的题目比较多,适合作为第一个分类的扩展
说明:递推算动归, 离散化算数据结构, 并查集算数据结构, 博弈算动归, 麻烦题一般都是不错的综合题, 最短路算图论,数据的有序化算排序
麻烦题:1697, 1712, 1713, 1720, 1729, 1765, 1772, 1858, 1872, 1960, 1963, 2050, 2122, 2162, 2219, 2237,
简单题目:1000, 1003, 1004, 1005, 1007, 1046, 1207, 1226, 1401, 1504, 1552, 1607, 1657, 1658, 1674, 1799, 1862, 1906, 1922, 1929, 1931, 1969, 1976, 2000, 2005, 2017, 2027, 2070, 2101, 2105, 2109, 2116, 2136, 2160, 2190, 2232, 2234, 2275, 2301, 2350, 2363, 2389, 2393, 2413, 2419, 推荐:1063, 1064, 1131, 1140, 1715, 2163,
杂题:1014, 1218, 1316, 1455, 1517, 1547, 1580, 1604, 1663, 1678, 1749, 1804, 2013, 2014, 2056, 2059, 2100, 2188, 2189, 2218, 2229, 2249, 2290, 2302, 2304, 2309, 2313, 2316, 2323, 2326, 2368, 2369, 2371, 2402, 2405, 2407, 推荐:1146, 1147, 1148, 1171, 1389, 1433, 1468, 1519, 1631, 1646, 1672, 1681, 1700, 1701, 1705, 1728, 1735, 1736, 1752, 1754, 1755, 1769, 1781, 1787, 1796, 1797, 1833, 1844, 1882, 1933, 1941, 1978, 2128, 2166, 2328, 2383, 2420,
高精度:1001, 1220, 1405, 1503,
排序:1002, 1318, 1877, 1928, 1971, 1974, 1990, 2001, 2002, 2092, 2379, 2388, 2418, 推荐:1423, 1694, 1723, 1727, 1763, 1788, 1828, 1838, 1840, 2201, 2376, 2377, 2380,
搜索容易:1128, 1166, 1176, 1231, 1256, 1270, 1321, 1543, 1606, 1664, 1731, 1742, 1745, 1847, 1915, 1950, 2038, 2157, 2182, 2183, 2381, 2386, 2426, 不易:1024, 1054, 1117, 1167, 1708, 1746, 1775, 1878, 1903, 1966, 2046, 2197, 2349, 推荐:1011, 1190, 1191, 1416, 1579, 1632, 1639, 1659, 1680, 1683, 1691, 1709, 1714, 1753, 1771, 1826, 1855, 1856, 1890, 1924, 1935, 1948, 1979, 1980, 2170, 2288, 2331, 2339, 2340,
数据结构容易:1182, 1656, 2021, 2023, 2051, 2153, 2227, 2236, 2247, 2352, 2395, 不易:1145, 1177, 1195, 1227, 1661, 1834, 推荐:1330, 1338, 1451, 1470, 1634, 1689, 1693, 1703, 1724, 1988, 2004, 2010, 2119, 2274,
动态规划容易:1018, 1050, 1083, 1088, 1125, 1143, 1157, 1163, 1178, 1179, 1189, 1208, 1276, 1322, 1414, 1456, 1458, 1609, 1644, 1664, 1690, 1699, 1740, 1742, 1887, 1926, 1936, 1952, 1953, 1958, 1959, 1962, 1975, 1989, 2018, 2029, 2033, 2063, 2081, 2082, 2181, 2184, 2192, 2231, 2279, 2329, 2336, 2346, 2353, 2355, 2356, 2385, 2392, 2424, 不易:1019, 1037, 1080, 1112, 1141, 1170, 1192, 1239, 1655, 1695, 1707, 1733, 1737, 1837, 1850, 1920, 1934, 1937, 1964, 2039, 2138, 2151, 2161, 2178, 推荐:1015, 1635, 1636, 1671, 1682, 1692, 1704, 1717, 1722, 1726, 1732, 1770, 1821, 1853, 1949, 2019, 2127, 2176, 2228, 2287, 2342, 2374, 2378, 2384, 2411,
字符串:1488, 1598, 1686, 1706, 1747, 1748, 1750, 1760, 1782, 1790, 1866, 1888, 1896, 1951, 2003, 2121, 2141, 2145, 2159, 2337, 2359, 2372, 2406, 2408,
贪心:1042, 1065, 1230, 1323, 1477, 1716, 1784,
图论容易:1161, 1164, 1258, 1175, 1308, 1364, 1776, 1789, 1861, 1939, 1940, 1943, 2075, 2139, 2387, 2394, 2421, 不易:1041, 1062, 1158, 1172, 1201, 1275, 1718, 1734, 1751, 1904, 1932, 2173, 2175, 2296, 网络流:1087, 1273, 1698, 1815, 2195, 匹配:1274, 1422, 1469, 1719, 2060, 2239, Euler:1237, 1637, 1394, 2230, 推荐:2049, 2186,
计算几何容易:1319, 1654, 1673, 1675, 1836, 2074, 2137, 2318, 不易:1685, 1687, 1696, 1873, 1901, 2172, 2333, 凸包:1113, 1228, 1794, 2007, 2187,
模拟容易:1006, 1008, 1013, 1016, 1017, 1169, 1298, 1326, 1350, 1363, 1676, 1786, 1791, 1835, 1970, 2317, 2325, 2390, 不易:1012, 1082, 1099, 1114, 1642, 1677, 1684, 1886,
数学容易:1061, 1091, 1142, 1289, 1305, 1306, 1320, 1565, 1665, 1666, 1730, 1894, 1914, 2006, 2042, 2142, 2158, 2174, 2262, 2305, 2321, 2348, 不易:1067, 1183, 1430, 1759, 1868, 1942, 2167, 2171, 2327, 推荐:1423, 1450, 1640, 1702, 1710, 1721, 1761, 1830, 1930, 2140,
参考技术A

第5章:常用算法设计(软件设计篇)免费下载

链接:https://pan.baidu.com/s/1EsbJAHii_AXsOL6JuSnRHw

提取码:vwj2    

《算法设计》是2007年清华大学出版社出版发行的图书,作者是Jon Kleinberg / Éva Tardos。

比赛支架放置算法

【中文标题】比赛支架放置算法【英文标题】:Tournament bracket placement algorithm 【发布时间】:2012-01-11 10:04:14 【问题描述】:

给定一个对手种子列表(例如种子 1 到 16),我正在尝试编写一个算法,该算法将导致该轮中头号种子玩最低种子,第二种子玩第二低种子等。

将 1 和 16、2 和 15 等分组为“比赛”相当容易,但我还需要确保较高的种子将在随后的回合中与较低的种子比赛。

正确放置的示例括号:

1 对 16
            1对8
8对9
                        1对4
4对13
            4对5
5对12
                                    1对2
2 对 15
            2 对 7
7对10
                        2 对 3
3 对 14
            3对6
6 比 11

如您所见,种子 1 和 2 只在决赛中相遇。

【问题讨论】:

这只是一个我完全没有考虑过的建议:从决赛开始。 这基本上是一个格雷码(如果您使用零索引)。要将标准(二进制反射)格雷码转换为您的编号系统,只需反转位并添加一个。 @Nabb – 我发现 this 看起来很有趣,但我无法理解代码(它是 Ruby,我一无所知) @darkangel:格雷码是到下一个码字的汉明距离为 1 时的代码,与二进制码不同,它仅在 1 位上有所不同。这是一个解释:dba.stackexchange.com/questions/7887/… 原理是正确的。但是,您可能更喜欢按以下特定顺序结束匹配:(1, 16), (9, 8), (5, 12), (13, 4), (3, 14), (11, 6) , (7, 10), (15, 2)。在这里查看我的答案:***.com/a/45566890/760777 【参考方案1】:

此 JavaScript 返回一个数组,其中每个偶数索引播放下一个奇数索引

function seeding(numPlayers)
  var rounds = Math.log(numPlayers)/Math.log(2)-1;
  var pls = [1,2];
  for(var i=0;i<rounds;i++)
    pls = nextLayer(pls);
  
  return pls;
  function nextLayer(pls)
    var out=[];
    var length = pls.length*2+1;
    pls.forEach(function(d)
      out.push(d);
      out.push(length-d);
    );
    return out;
  


> seeding(2)
[1, 2]
> seeding(4)
[1, 4, 2, 3]
> seeding(8)
[1, 8, 4, 5, 2, 7, 3, 6]
> seeding(16)
[1, 16, 8, 9, 4, 13, 5, 12, 2, 15, 7, 10, 3, 14, 6, 11]

【讨论】:

似乎正确。但是,您可能更喜欢按以下特定顺序结束匹配:(1, 16), (9, 8), (5, 12), (13, 4), (3, 14), (11, 6) , (7, 10), (15, 2)。在这里查看我的答案:***.com/a/45572051/760777【参考方案2】:

根据您的假设,选手 1 和 2 将参加决赛,选手 1-4 参加半决赛,选手 1-8 参加四分之一决赛等等,因此您可以按照 AakashM 的建议从决赛递归地构建锦标赛.将锦标赛想象成一棵树,其根是最终的。

在根节点中,您的玩家是 1, 2。

要递归扩展树到下一层,将树中最底层的所有节点,一个接一个,并为它们分别创建两个子节点,并将原始节点的玩家之一放置到每个节点创建的子节点。然后添加下一层玩家并将它们映射到游戏中,以便新添加的最差玩家与现有的最佳玩家对战。

这里是第一轮算法:

 1,2  --- create next layer

       1, _
      /         --- now fill the empty slots
 1,2
      \2, _

       1, 4   --- the slots filled in reverse order
      /         
 1,2
      \2, 3   --- create next layer again


             /1, _
       1, 4
      /      \4, _
 1,2                  --- again fill
      \      /2, _
       2, 3
             \3, _

             /1, 8
       1, 4
      /      \4, 5    --- ... and so on
 1,2
      \      /2, 7
       2, 3
             \3, 6

如您所见,它会生成与您发布的相同的树。

【讨论】:

非常有趣的想法,虽然我得考虑如何将它翻译成代码。 我有这个想法以及另一个关于如何在不倒退的情况下做到这一点的想法。我认为他们最终归结为同样的事情,虽然真的。当然,根据每个玩家的种子计算位置的方法确实非常复杂,翻译成代码可能比这更复杂。我当然会采用这种方法。【参考方案3】:

我想出了以下算法。它可能不是超级高效,但我认为它真的不需要。它是用 PHP 编写的。

<?php
    $players = range(1, 32);
    $count = count($players);
    $numberOfRounds = log($count / 2, 2);

    // Order players.
    for ($i = 0; $i < $numberOfRounds; $i++) 
        $out = array();
        $splice = pow(2, $i); 

        while (count($players) > 0) 

            $out = array_merge($out, array_splice($players, 0, $splice));
            $out = array_merge($out, array_splice($players, -$splice));

                    

        $players = $out;
    

    // Print match list.
    for ($i = 0; $i < $count; $i++) 
        printf('%s vs %s<br />%s', $players[$i], $players[++$i], PHP_EOL);
    
?>

【讨论】:

对此我有一个小问题。这对喂食后续回合有何作用? 我不太清楚你的意思——这只是确保最高种子将在每一轮中扮演最低种子(而第二高的将扮演第二低的种子,等等) 这是一个伟大而简单的解决方案。我做了一个小修改以提高效率。【参考方案4】:

我还写了一个用 PHP 编写的解决方案。我看到了 Patrik Bodin 的回答,但认为一定有更简单的方法。

它完成了黑暗天使的要求:它返回所有种子在正确的位置。比赛与他的示例相同,但按照 更漂亮 的顺序,种子 1 和种子 16 位于模式之外(如网球锦标赛中所见)。

如果没有冷门(意味着高种子玩家总是从低种子玩家手中获胜),您将在决赛中以 1 号种子对 2 号种子结束比赛。

它实际上做了两件事:

    它显示了正确的顺序(这是将轮空放在正确位置的要求)

    它会在正确的位置填充字节(如果需要)

关于单淘汰括号应该是什么样子的完美解释:http://blog.playdriven.com/2011/articles/the-not-so-simple-single-elimination-advantage-seeding/

16 位参与者的代码示例:

<?php

define('NUMBER_OF_PARTICIPANTS', 16);

$participants = range(1,NUMBER_OF_PARTICIPANTS);
$bracket = getBracket($participants);
var_dump($bracket);

function getBracket($participants)

    $participantsCount = count($participants);  
    $rounds = ceil(log($participantsCount)/log(2));
    $bracketSize = pow(2, $rounds);
    $requiredByes = $bracketSize - $participantsCount;

    echo sprintf('Number of participants: %d<br/>%s', $participantsCount, PHP_EOL);
    echo sprintf('Number of rounds: %d<br/>%s', $rounds, PHP_EOL);
    echo sprintf('Bracket size: %d<br/>%s', $bracketSize, PHP_EOL);
    echo sprintf('Required number of byes: %d<br/>%s', $requiredByes, PHP_EOL);    

    if($participantsCount < 2)
    
        return array();
    

    $matches = array(array(1,2));

    for($round=1; $round < $rounds; $round++)
    
        $roundMatches = array();
        $sum = pow(2, $round + 1) + 1;
        foreach($matches as $match)
        
            $home = changeIntoBye($match[0], $participantsCount);
            $away = changeIntoBye($sum - $match[0], $participantsCount);
            $roundMatches[] = array($home, $away);
            $home = changeIntoBye($sum - $match[1], $participantsCount);
            $away = changeIntoBye($match[1], $participantsCount);
            $roundMatches[] = array($home, $away);
        
        $matches = $roundMatches;
    

    return $matches;



function changeIntoBye($seed, $participantsCount)

    //return $seed <= $participantsCount ?  $seed : sprintf('%d (= bye)', $seed);  
    return $seed <= $participantsCount ?  $seed : null;


?>

输出:

Number of participants: 16
Number of rounds: 4
Bracket size: 16
Required number of byes: 0
C:\projects\draw\draw.php:7:
array (size=8)
  0 => 
    array (size=2)
      0 => int 1
      1 => int 16
  1 => 
    array (size=2)
      0 => int 9
      1 => int 8
  2 => 
    array (size=2)
      0 => int 5
      1 => int 12
  3 => 
    array (size=2)
      0 => int 13
      1 => int 4
  4 => 
    array (size=2)
      0 => int 3
      1 => int 14
  5 => 
    array (size=2)
      0 => int 11
      1 => int 6
  6 => 
    array (size=2)
      0 => int 7
      1 => int 10
  7 => 
    array (size=2)
      0 => int 15
      1 => int 2

如果你把 16 变成 6,你会得到:

Number of participants: 6
Number of rounds: 3
Bracket size: 8
Required number of byes: 2
C:\projects\draw\draw.php:7:
array (size=4)
  0 => 
    array (size=2)
      0 => int 1
      1 => null
  1 => 
    array (size=2)
      0 => int 5
      1 => int 4
  2 => 
    array (size=2)
      0 => int 3
      1 => int 6
  3 => 
    array (size=2)
      0 => null
      1 => int 2

【讨论】:

【参考方案5】:
# Here's one in python - it uses nested list comprehension to be succinct:

from math import log, ceil

def seed( n ):
    """ returns list of n in standard tournament seed order

    Note that n need not be a power of 2 - 'byes' are returned as zero
    """

    ol = [1]

    for i in range( ceil( log(n) / log(2) ) ):

        l = 2*len(ol) + 1

        ol = [e if e <= n else 0 for s in [[el, l-el] for el in ol] for e in s]

    return ol

【讨论】:

【参考方案6】:

对于 JavaScript 代码,请使用以下两个函数之一。前者体现了命令式风格并且速度更快。后者具有递归性和简洁性,但仅适用于相对较少的团队(

// imperative style
function foo(n) 
  const arr = new Array(n)
  arr[0] = 0
  for (let i = n >> 1, m = 1; i >= 1; i >>= 1, m = (m << 1) + 1) 
    for (let j = n - i; j > 0; j -= i) 
      arr[j] = m - arr[j -= i]
    
  
  return arr

在这里,您通过镜像已占用的点来一一填充。例如,一号种子队(即号码0)进入最高点。第二个 (1) 占据括号另一半的相反位置。第三队 (2) 在他们的一半括号中镜像1 等等。尽管存在嵌套循环,但该算法具有取决于团队数量的线性时间复杂度。

这里是递归方法:

// functional style
const foo = n =>
  n === 1 ? [0] : foo(n >> 1).reduce((p, c) => [...p, c, n - c - 1], [])

基本上,您执行与前一个函数相同的镜像,但递归:

对于n = 1 团队,它只是[0]

对于 n = 2 团队,将此函数应用于参数 n-1(即 1) 并获取 [0]。然后通过插入 mirrored 来使数组加倍 它们之间的元素在偶数位置。因此,[0] 变为 [0, 1]

对于n = 4 团队,您执行相同的操作,因此[0, 1] 变为[0, 3, 1, 2]

如果您想获得人类可读的输出,请将结果数组的每个元素加一:

const readableArr = arr.map(i => i + 1)

【讨论】:

【参考方案7】: 在每轮比赛中按种子标准对球队进行排序 (如果一轮有n队)第i个位置的队与第n-i+1队比赛

【讨论】:

我需要将球队安排在第一轮,这样进入下一轮的头号种子将自动匹配头号种子和尾号种子等。您可以假设头号种子出于算法的目的,总是赢得比赛。【参考方案8】:

由于在搜索该主题时会出现此问题,并且无法找到解决问题的另一个答案并将种子按“更漂亮”的顺序排列,因此我将添加来自 darkangel 的 PHP 代码版本。我还添加了与更高种子玩家轮空的可能性。

这是在 OO 环境中编码的,因此参与者的数量在 $this->finalists 中,而byes 的数量在 $this->byes 中。我只测试了没有 byes 和两个 byes 的代码。

  public function getBracket() 
      $players = range(1, $this->finalists);
      for ($i = 0; $i < log($this->finalists / 2, 2); $i++) 
        $out = array();
        $reverse = false;
        foreach ($players as $player) 
          $splice = pow(2, $i);
          if ($reverse) 
            $out = array_merge($out, array_splice($players, -$splice));
            $out = array_merge($out, array_splice($players, 0, $splice));
            $reverse = false;
           else 
            $out = array_merge($out, array_splice($players, 0, $splice));
            $out = array_merge($out, array_splice($players, -$splice));
            $reverse = true;
          
        
        $players = $out;
      
      if ($this->byes) 
        for ($i = 0; $i < $this->byes; $i++ ) 
          for ($j = (($this->finalists / pow(2, $i)) - 1); $j > 0; $j--) 
            $newPlace = ($this->finalists / pow(2, $i)) - 1;
            if ($players[$j] > ($this->finalists / (pow(2 ,($i + 1))))) 
              $player = $players[$j];
              unset($players[$j]);
              array_splice($players, $newPlace, 0, $player);
            
          
        
        for ($i = 0; $i < $this->finalists / (pow(2, $this->byes)); $i++ ) 
          $swap[] = $players[$i];
        
        for ($i = 0; $i < $this->finalists /(pow(2, $this->byes)); $i++ ) 
          $players[$i] = $swap[count($swap) - 1 - $i];
        
        return array_reverse($players);
      
      return $players;
    

【讨论】:

【参考方案9】:

我开发了一个 PHP / Laravel 插件,该插件生成带有/不带有初步循环的括号。也许它对你有用,我不知道你使用的是什么技术。这里是github。

https://github.com/xoco70/kendo-tournaments

希望对你有帮助!

【讨论】:

【参考方案10】:

A C 版本。

int * pctournamentSeedArray(int PlayerCnt)

    int * Array;
    int * PrevArray;
    int i;

    Array = meAlloc(sizeof(int) * PlayerCnt);

    if (PlayerCnt == 2)
    
        Array[0] = 0;
        Array[1] = 1;
        return Array;
    

    PrevArray = pctournamentSeedArray(PlayerCnt / 2);
    for (i = 0; i < PlayerCnt;i += 2)
    
        Array[i] = PrevArray[i / 2];
        Array[i + 1] = (PlayerCnt - 1) - Array[i] ;
    
    meFree(PrevArray);
    return Array;

【讨论】:

以上是关于算法设计比赛做啥算法好的主要内容,如果未能解决你的问题,请参考以下文章

《算法之道》精华 算法设计部分

算法设计和算法分析有啥区别? [关闭]

游戏的匹配算法

算法分析与设计题目

算法之循环赛日程表

算法概论