动态编程/记忆(计算三元组)

时间:2012-04-13 19:51:15

标签: c++ python dynamic-programming memoization

我有一个像这样的数字列表(随机生成,在每个子组中排序的数字。这些组是不相交的,这意味着你不会在多个组中找到给定的数字):

L=[[19,18,14,9,4],[15,12,11,10,6,5],[8],[16,13,3,2],[17,7,1]]

我正在尝试计算我可以创建递减三元组的方式。

reduce-triplet是三元组,我们从左到右扫描列表并从组中取出元素1,然后从另一个组中取出元素2,然后从另一个组中取出元素3,其中最终结果应按降序排列自然。

例如,(19,11,7)是一个有效的递减三元组,因为这些数字来自不同的子列表,并且是递减的,自然顺序(19在11之前出现在主列表中的7之前)。 / p>

用一个反例来澄清:(15,9,8)不会是一个递减的三元组,因为9来自早于15的子列表。

我正在尝试使用动态编程或某种记忆来计算递减三元组的数量。设置如下的循环结构很容易:

for i in xrange(0,len(L)-2):
    for j in xrange(i+1, len(L)-1):
        for k in xrange(j+1, len(L)):
            for item1 in L[i]:
                for item2 in L[j]:
                    if item1>item2:
                        for item3 in L[k]:
                            if item2>item3:
                                count+=1

但是对于较大的列表,它不能很好地扩展。我觉得应该有一些方法可以通过列表一次计算三胞胎。例如,如果我知道一个数字大于另一个数字(或者如果我知道它的数量大于多少),我觉得我应该能够在以后重新使用这些信息。

例如,我知道16可以在7或1之前出现在有效的三元组中。那是2对“。”因此,如果我想在列表中向后移动时创建一个三元组,我看一下,比方说,19,我应该可以说“它大于16,因此你可以创建两个三元组,因为我们知道16大于2个数字。“等等。

我只是在大声思考,但会欣赏一些见解。

2 个答案:

答案 0 :(得分:0)

尝试以下itertool解决方案

import itertools
import time

L= [
    {19, 18, 14, 9, 4},
    {15, 12, 11, 10, 6, 5},
    {8},
    {16, 13, 3, 2},
    {17, 7, 1},
]


start = time.time()
for i in xrange(20000):
    count = 0
    for i in xrange(0,len(L)-2):
        for j in xrange(i+1, len(L)-1):
            for k in xrange(j+1, len(L)):
                for item1 in L[i]:
                    for item2 in L[j]:
                        if item1>item2:
                            for item3 in L[k]:
                                if item2>item3:
                                    count+=1

print
print time.time() - start

# result: 3.1542930603

start = time.time()
for i in xrange(20000):
    sum(1 for l1, l2, l3 in itertools.combinations(L, 3) for a, b, c in itertools.product(l1, l2, l3) if a > b > c)

print
print time.time() - start

# result: 1.94973897934

答案 1 :(得分:0)

i0之间使用索引n而不是嵌套循环。 跟踪当前三元组的最后一个元素。 并使用备忘录使其高效。

L=[[19,18,14,9,4],[15,12,11,10,6,5],[8],[16,13,3,2],[17,7,1]]

n=len(L)

memo = {}
def f(i,j,last):
  if (i,j,last) in memo:
    return memo[(i,j,last)]
  if j==3:
    return 1
  if i==n:
    return 0
  res=0
  # take one from L[i]
  for x in L[i]:
    if last > x:
      res+=f(i+1,j+1,x)
  # don't take any element from L[i]
  res += f(i+1,j,last)
  memo[(i,j,last)] = res
  return res

BIG = 10**9
print f(0,0,BIG)