在给定输入中查找最大路径

时间:2012-04-07 10:09:35

标签: python

我把它作为家庭作业,我需要在python中完成。

Problem:
The Maximum Route is defined as the maximum total by traversing from the tip of the triangle to its base. Here the maximum route is (3+7+4+9) 23.

3
7 4
2 4 6
8 5 9 3

Now, given a certain triangle, my task is to find the Maximum Route for it. 

不确定怎么做....

4 个答案:

答案 0 :(得分:3)

我们可以使用回溯来解决这个问题。要为任何给定行中的三角形的每个元素执行此操作,我们必须确定当前元素和下一行中三个连接的邻居之和的最大值,或

if elem = triangle[row][col] and the next row is triangle[row+1]

then backtrack_elem = max([elem + i for i in connected_neighbors of col in row])

首先尝试找到确定connected_neighbors of col in row

的方法

对于位置上的elem(row,col),row = next中的连接邻居将[next[col-1],next[col],next[col+1]]提供col - 1 >=0col+1 < len(next)。这是一个示例实现

>>> def neigh(n,sz):
    return [i for i in (n-1,n,n+1) if 0<=i<sz]

这将返回已连接邻居的索引。

现在我们可以将backtrack_elem = max([elem + i for i in connected_neighbors of col in row])写为

triangle[row][i] = max([elem + next[n] for n in neigh(i,len(next))])

如果我们迭代迭代三角形并且curr是任何给定的行然后我是行的第i个col索引那么我们可以写

curr[i]=max(next[n]+e for n in neigh(i,len(next)))

现在我们必须迭代读取当前和下一行的三角形。这可以作为

完成
for (curr,next) in zip(triangle[-2::-1],triangle[::-1]):

然后我们使用enumerate生成索引的元组和elem本身

for (i,e) in enumerate(curr):

俱乐部然后我们一起

>>> for (curr,next) in zip(triangle[-2::-1],triangle[::-1]):
    for (i,e) in enumerate(curr):
        curr[i]=max(next[n]+e for n in neigh(i,len(next)))

但是上面的操作具有破坏性,我们必须创建原始三角形的副本并对其进行处理

route = triangle # This will not work, because in python copy is done by reference
route = triangle[:] #This will also not work, because triangle is a list of list
                    #and individual list would be copied with reference

所以我们必须使用deepcopy模块

import copy
route = copy.deepcopy(triangle) #This will work

并将遍历重写为

>>> for (curr,next) in zip(route[-2::-1],route[::-1]):
    for (i,e) in enumerate(curr):
        curr[i]=max(next[n]+e for n in neigh(i,len(next)))

我们最终得到另一个三角形,每个elem都可以提供最高的路线成本。要获得实际路线,我们必须使用原始三角形并向后计算

因此对于索引为[row,col]的元素,最高路由成本为route [row] [col]。如果它遵循最大路线,则下一个elem应该是连接的邻居,路由成本应该是route [row] [col] - orig [row] [col]。如果我们按行迭代,我们可以写为

i=[x for x in neigh(next,i) if x == curr[i]-orig[i]][0]
orig[i]

我们应该从峰值元素开始向下循环。因此我们有

>>> for (curr,next,orig) in zip(route,route[1:],triangle):
    print orig[i],
    i=[x for x in neigh(i,len(next)) if next[x] == curr[i]-orig[i]][0]

让我们举一些复杂的例子,因为你的解决方案太简单了

>>> triangle=[
          [3],
          [7, 4],
          [2, 4, 6],
          [8, 5, 9, 3],
          [15,10,2, 7, 8]
         ]

>>> route=copy.deepcopy(triangle) # Create a Copy

生成路线

>>> for (curr,next) in zip(route[-2::-1],route[::-1]):
    for (i,e) in enumerate(curr):
        curr[i]=max(next[n]+e for n in neigh(i,len(next)))


>>> route
[[37], [34, 31], [25, 27, 26], [23, 20, 19, 11], [15, 10, 2, 7, 8]]

最后我们计算路线

>>> def enroute(triangle):
    route=copy.deepcopy(triangle) # Create a Copy
    # Generating the Route
    for (curr,next) in zip(route[-2::-1],route[::-1]): #Read the curr and next row
        for (i,e) in enumerate(curr):
            #Backtrack calculation
            curr[i]=max(next[n]+e for n in neigh(i,len(next)))
    path=[] #Start with the peak elem
    for (curr,next,orig) in zip(route,route[1:],triangle): #Read the curr, next and orig row
        path.append(orig[i])
        i=[x for x in neigh(i,len(next)) if next[x] == curr[i]-orig[i]][0]
    path.append(triangle[-1][i]) #Don't forget the last row which
    return (route[0],path)

测试我们的三角形

>>> enroute(triangle)
([37], [3, 7, 4, 8, 15])

阅读jamylak的评论,我意识到这个问题与欧拉18类似,但不同之处在于表现形式。欧拉18中的问题考虑了金字塔,其中这个问题中的问题是直角三角形。你可以阅读我对他评论的回复,我解释了结果会有所不同的原因。然而,这个问题可以很容易地移植到与Euler 18一起使用。这是端口

>>> def enroute(triangle,neigh=lambda n,sz:[i for i in (n-1,n,n+1) if 0<=i<sz]):
    route=copy.deepcopy(triangle) # Create a Copy
    # Generating the Route
    for (curr,next) in zip(route[-2::-1],route[::-1]): #Read the curr and next row
        for (i,e) in enumerate(curr):
            #Backtrack calculation
            curr[i]=max(next[n]+e for n in neigh(i,len(next)))
    path=[] #Start with the peak elem
    for (curr,next,orig) in zip(route,route[1:],triangle): #Read the curr, next and orig row
        path.append(orig[i])
        i=[x for x in neigh(i,len(next)) if next[x] == curr[i]-orig[i]][0]
    path.append(triangle[-1][i]) #Don't forget the last row which
    return (route[0],path)

>>> enroute(t1) # For Right angle triangle
([1116], [75, 64, 82, 87, 82, 75, 77, 65, 41, 72, 71, 70, 91, 66, 98])
>>> enroute(t1,neigh=lambda n,sz:[i for i in (n,n+1) if i<sz]) # For a Pyramid
([1074], [75, 64, 82, 87, 82, 75, 73, 28, 83, 32, 91, 78, 58, 73, 93])
>>>

答案 1 :(得分:2)

即使这是作业,@ abhijit给出了答案,所以我也会这样做!

要理解这一点,你需要阅读python生成器,可能需要google它;)

>>> triangle=[
          [3],
          [7, 4],
          [2, 4, 6],
          [8, 5, 9, 3]
         ]

第一步是找到所有可能的路线

>>> def routes(rows,current_row=0,start=0): 
        for i,num in enumerate(rows[current_row]): #gets the index and number of each number in the row
            if abs(i-start) > 1:   # Checks if it is within 1 number radius, if not it skips this one. Use if not (0 <= (i-start) < 2) to check in pyramid
                continue
            if current_row == len(rows) - 1: # We are iterating through the last row so simply yield the number as it has no children
                yield [num]
            else:
                for child in routes(rows,current_row+1,i): #This is not the last row so get all children of this number and yield them
                    yield [num] + child

这给出了

>>> list(routes(triangle))
[[3, 7, 2, 8], [3, 7, 2, 5], [3, 7, 4, 8], [3, 7, 4, 5], [3, 7, 4, 9], [3, 4, 2, 8], [3, 4, 2, 5], [3, 4, 4, 8], [3, 4, 4, 5], [3, 4, 4, 9], [3, 4, 6, 5], [3, 4, 6, 9], [3, 4, 6, 3]]

为了让max变得简单,max接受生成器,因为它们是可迭代的,所以我们不需要将它转换为列表。

>>> max(routes(triangle),key=sum)
[3, 7, 4, 9]

答案 2 :(得分:1)

我会就这个具体案例给你一些提示。尝试自己为n层三角形创建一个通用函数。

triangle=[
          [3],
          [7, 4],
          [2, 4, 6],
          [8, 5, 9, 3]
         ]

possible_roads={}

for i1 in range(1):
    for i2 in range(max(i1-1,0),i1+2):
        for i3 in range(max(i2-1,0),i2+2):
            for i4 in range(max(i3-1,0),i3+2):
                road=(triangle[0][i1],triangle[1][i2],triangle[2][i3],triangle[3][i4])
                possible_roads[road]=sum(road)

print "Best road: %s (sum: %s)" % (max(possible_roads), possible_roads[max(possible_roads)])

[编辑] 由于每个人都在这里发布了他们的答案。

triangle=[
          [3],
          [7, 4],
          [2, 4, 6],
          [8, 5, 9, 3]
         ]

def generate_backtrack(triangle):
    n=len(triangle)
    routes=[[{'pos':i,'val':triangle[n-1][i]}] for i in range(n)]
    while n!=1:
        base_routes=[]
        for idx in range(len(routes)):
            i=routes[idx][-1]['pos'] #last node
            movements=range(
                                max(0,i-1),
                                min(i+2,n-1)
                            )
            for movement in movements:
                base_routes.append(routes[idx]+[{'pos':movement,'val':triangle[n-2][movement]}])

        n-=1
        routes=base_routes
    return [[k['val'] for k in j] for j in routes]

print sorted(generate_backtrack(triangle),key=sum,reverse=True)[0][::-1]

答案 3 :(得分:0)

我的回答

def maxpath(listN):
  liv = len(listN) -1
  return calcl(listN,liv)

def calcl(listN,liv):
  if liv == 0:
    return listN[0]
  listN[liv-1] = [(listN[liv-1][i]+listN[liv][i+1],listN[liv-1][i]+listN[liv][i]) \
            [ listN[liv][i] > listN[liv][i+1] ] for i in range(0,liv)]
  return calcl(listN,liv-1)

输出

l5=[
      [3],
      [7, 4],
      [2, 4, 6],
      [8, 5, 9, 3],
      [15,10,2, 7, 8]
     ]
print(maxpath(l5)
>>>[35]