Python 递归和动态规划的不同结果

Python 递归和动态规划的不同结果,python,algorithm,python-2.7,Python,Algorithm,Python 2.7,正在解决以下问题 问题 from collections import defaultdict def move_up_right(remaining_right, remaining_up, prefix, result): if remaining_up == 0 and remaining_right == 0: result.append(''.join(prefix[:])) return if remaining_right >

正在解决以下问题

问题

from collections import defaultdict
def move_up_right(remaining_right, remaining_up, prefix, result):
    if remaining_up == 0 and remaining_right == 0:
        result.append(''.join(prefix[:]))
        return
    if remaining_right > 0:
        prefix.append('r')
        move_up_right(remaining_right-1, remaining_up, prefix, result)
        prefix.pop(-1)
    if remaining_up > 0:
        prefix.append('u')
        move_up_right(remaining_right, remaining_up-1, prefix, result)
        prefix.pop(-1)
def move_up_right_v2(remaining_right, remaining_up):
    # key is a tuple (given remaining_right, given remaining_up),
    # value is solutions in terms of list
    dp = defaultdict(list)
    dp[(0,1)].append('u')
    dp[(1,0)].append('r')
    for right in range(1, remaining_right+1):
        for up in range(1, remaining_up+1):
            for s in dp[(right-1,up)]:
                dp[(right,up)].append(s+'r')
            for s in dp[(right,up-1)]:
                dp[(right,up)].append(s+'u')
    return dp[(right, up)]

if __name__ == "__main__":
    result = []
    move_up_right(2,3,[],result)
    print result
    print '============'
    print move_up_right_v2(2,3)
给定一个m*n网格,其中一个允许向上或向右移动,找到两个网格点之间的不同路径

我写了一个递归版本和一个动态编程版本,但是它们返回不同的结果,有什么想法吗

源代码

from collections import defaultdict
def move_up_right(remaining_right, remaining_up, prefix, result):
    if remaining_up == 0 and remaining_right == 0:
        result.append(''.join(prefix[:]))
        return
    if remaining_right > 0:
        prefix.append('r')
        move_up_right(remaining_right-1, remaining_up, prefix, result)
        prefix.pop(-1)
    if remaining_up > 0:
        prefix.append('u')
        move_up_right(remaining_right, remaining_up-1, prefix, result)
        prefix.pop(-1)
def move_up_right_v2(remaining_right, remaining_up):
    # key is a tuple (given remaining_right, given remaining_up),
    # value is solutions in terms of list
    dp = defaultdict(list)
    dp[(0,1)].append('u')
    dp[(1,0)].append('r')
    for right in range(1, remaining_right+1):
        for up in range(1, remaining_up+1):
            for s in dp[(right-1,up)]:
                dp[(right,up)].append(s+'r')
            for s in dp[(right,up-1)]:
                dp[(right,up)].append(s+'u')
    return dp[(right, up)]

if __name__ == "__main__":
    result = []
    move_up_right(2,3,[],result)
    print result
    print '============'
    print move_up_right_v2(2,3)

动态编程版本的问题在于它没有考虑从多个向上移动(
'uu…'
)或多个向右移动(
'rr…'
)开始的路径

在执行主循环之前,您需要为从
1
剩余+1
的每个
x
填充
dp[(x,0)]
,并为从
1
剩余+1
的每个
y
填充

换言之,替换为:

dp[(0,1)].append('u')
dp[(1,0)].append('r')
为此:

for right in range(1, remaining_right+1):
    dp[(right,0)].append('r'*right)
for up in range(1, remaining_up+1):
    dp[(0,up)].append('u'*up)

在版本2中,应该在0而不是1开始for循环。如果从1开始,则缺少可能的排列,即首先遍历最底部的行或最左侧的列

将版本2更改为:

def move_up_right_v2(remaining_right, remaining_up):
    # key is a tuple (given remaining_right, given remaining_up),
    # value is solutions in terms of list
    dp = defaultdict(list)
    dp[(0,1)].append('u')
    dp[(1,0)].append('r')
    for right in range(0, remaining_right+1):
        for up in range(0, remaining_up+1):
            for s in dp[(right-1,up)]:
                dp[(right,up)].append(s+'r')
            for s in dp[(right,up-1)]:
                dp[(right,up)].append(s+'u')
    return dp[(right, up)]  
然后:

result = []
move_up_right(2,3,[],result)

set(move_up_right_v2(2,3)) == set(result)
True
只是为了好玩。。。另一种方法是:

from itertools import permutations

list(map(''.join, set(permutations('r'*2+'u'*3, 5))))

在问题中包含您的输入数据、输出数据和预期的输出数据可能会有所帮助。@Snakechermerb,我的输入数据包含在源代码中,请参见
2,3,[],result
,即向右移动2步,向上移动3步。如果你对我原来的问题有什么想法,那就太好了。你还有什么希望呢?@greybeard,它已经很好了,谢谢你了。@greybeard,我对这个问题有了一些新的想法,我有了一个新的帖子,如果你有任何想法,那就太好了=>谢谢bunji的回复,投票并将其标记为答案。Grant bounty points.BTW,bunji,我对这个问题有一些新的想法,有一个新的帖子,如果你有任何想法,它会很棒=>BTW,user3290797,我对这个问题有一些新想法,有一个新帖子,如果你有任何想法,它会很棒=>