【问题标题】:Dynamic programming gives different result with cache implementation动态编程通过缓存实现给出不同的结果
【发布时间】:2014-10-02 07:00:03
【问题描述】:

我正在做一个动态编程算法,在整个晚上毫无希望地调试我的程序之后,我都没有答案了。基本上,当我使用缓存来存储中间结果时,我的程序会返回错误的答案。这是我的程序:

def cachecost(cache, i, j, seq1, seq2):
    if cache[i][j] is None:
        v1 = v2 = v3 = v4 = None

        if i > 0 and j > 0:
            v1 = cachecost(cache, i-1, j-1, seq1, seq2) + 5
        if i > 0 and j >= 0:
            v2 = cachecost(cache, i-1, j, seq1, seq2) + 1
        if i >= 0 and j > 0:
            v3 = cachecost(cache, i, j-1, seq1, seq2) + 1
        if i == 0 and j == 0:
            v4 = 0

        cache[i][j] = max(v1, v2, v3, v4)
    return cache[i][j]


def cost(cache, i, j, seq1, seq2):
    v1 = v2 = v3 = v4 = None

    if i > 0 and j > 0:
        v1 = cost(cache, i-1, j-1, seq1, seq2) + 5
    if i > 0 and j >= 0:
        v2 = cost(cache, i-1, j, seq1, seq2) + 1
    if i >= 0 and j > 0:
        v3 = cost(cache, i, j-1, seq1, seq2) + 1
    if i == 0 and j == 0:
        v4 = 0

    cache[i][j] = max(v1, v2, v3, v4)
    return max(v1, v2, v3, v4)


def main():
    seq1 = 'AATAAT'
    seq2 = 'AAGG'
    cache = [[None] * (len(seq2) + 1)] * (len(seq1) + 1)
    cachescore = cachecost(cache, len(seq1), len(seq2), seq1, seq2)
    score = cost(cache, len(seq1), len(seq2), seq1, seq2)
    print 'Score without cache: %s, score with cache: %s' % (cachescore, score)


# Handle command line execution
if __name__ == '__main__':
    main()

该算法基本上通过递归计算i * j 表,其中缓存实现确保表中的每个条目只计算一次。

运行程序会产生以下输出:

Score without cache: 36, score with cache: 22

我在这里做错了什么?

【问题讨论】:

    标签: python recursion dynamic-programming


    【解决方案1】:

    实际问题出在这一行

    cache = [[None] * (len(seq2) + 1)] * (len(seq1) + 1)
    

    它首先创建一个大小为len(seq2) + 1Nones 列表,然后创建另一个大小为len(seq1) + 1 的列表,其中所有元素都是对同一Nones 列表的引用。因此,如果您要更改其中任何一个,则该更改也会反映在所有其他更改中。例如,

    lists = [[None] * 2] * 3
    print lists
    # [[None, None], [None, None], [None, None]]
    lists[0][1] = 1
    print lists
    # [[None, 1], [None, 1], [None, 1]]
    

    所以,你需要像这样创建它

    cache = [[None] * (len(seq2) + 1) for _ in range(len(seq1) + 1)]
    

    现在,在每次迭代中,将创建一个新的 Nones 列表,并将它们全部放在一个新列表中。

    lists = [[None] * 2 for _ in range(3)]
    print lists
    # [[None, None], [None, None], [None, None]]
    lists[0][1] = 1
    print lists
    # [[None, 1], [None, None], [None, None]]
    

    【讨论】:

    • 非常感谢!很有道理。
    • 天啊,你得快点过来。 :) 不错的答案,thefourtheye。
    • @soren.qvist :有关可爱图表的更多信息,请参阅 SO 成员 Ned Batchelder 的 Facts and myths about Python names and values
    猜你喜欢
    • 1970-01-01
    • 2012-03-20
    • 2018-11-28
    • 1970-01-01
    • 2018-04-30
    • 2015-11-29
    • 1970-01-01
    • 1970-01-01
    • 2017-04-23
    相关资源
    最近更新 更多