我把它作为家庭作业,我需要在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.
不确定怎么做....
答案 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 >=0
和col+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]