有一个数字列表。
该列表将被分为2个大小相等的列表,并且总和的差异最小。总和必须打印出来。
#Example: >>>que = [2,3,10,5,8,9,7,3,5,2] >>>make_teams(que) 27 27
在某些情况下,以下代码算法是否存在错误?
如何优化和/或pythonize?
def make_teams(que): que.sort() if len(que)%2: que.insert(0,0) t1,t2 = [],[] while que: val = (que.pop(), que.pop()) if sum(t1)>sum(t2): t2.append(val[0]) t1.append(val[1]) else: t1.append(val[0]) t2.append(val[1]) print min(sum(t1),sum(t2)), max(sum(t1),sum(t2)), "\n"
问题来自http://www.codechef.com/problems/TEAMSEL/
新解决方案
这是启发式剔除的广度优先搜索。该树限于玩家的深度/ 2。玩家总和限制为totalscores / 2。玩家人数为100,解决问题大约需要10秒。
def team(t): iterations = range(2, len(t)/2+1) totalscore = sum(t) halftotalscore = totalscore/2.0 oldmoves = {} for p in t: people_left = t[:] people_left.remove(p) oldmoves[p] = people_left if iterations == []: solution = min(map(lambda i: (abs(float(i)-halftotalscore), i), oldmoves.keys())) return (solution[1], sum(oldmoves[solution[1]]), oldmoves[solution[1]]) for n in iterations: newmoves = {} for total, roster in oldmoves.iteritems(): for p in roster: people_left = roster[:] people_left.remove(p) newtotal = total+p if newtotal > halftotalscore: continue newmoves[newtotal] = people_left oldmoves = newmoves solution = min(map(lambda i: (abs(float(i)-halftotalscore), i), oldmoves.keys())) return (solution[1], sum(oldmoves[solution[1]]), oldmoves[solution[1]]) print team([90,200,100]) print team([2,3,10,5,8,9,7,3,5,2]) print team([1,1,1,1,1,1,1,1,1,9]) print team([87,100,28,67,68,41,67,1]) print team([1, 1, 50, 50, 50, 1000]) #output #(200, 190, [90, 100]) #(27, 27, [3, 9, 7, 3, 5]) #(5, 13, [1, 1, 1, 1, 9]) #(229, 230, [28, 67, 68, 67]) #(150, 1002, [1, 1, 1000])
还要注意,我试图使用GS的描述来解决此问题,但是仅通过存储运行总计就无法获得足够的信息。而且,如果您同时存储 了 项目数和总数,则除了保留不必要的数据外,其他方法与该解决方案相同。因为您只需要将n-1和n次迭代保持为numplayers / 2。
我有一个基于二项式系数的旧式详尽清单(历史记录)。它很好地解决了长度为10的示例问题,但后来我看到比赛的人数不超过100。