【问题标题】:SPOJ Alphcode iterative dynamic programmingSPOJ Alphacode 迭代动态规划
【发布时间】:2013-11-26 13:35:16
【问题描述】:

我能够使用递归 DP 解决标题中给出的问题,但得到了 TLE。这是因为输入字符串可能有大约 5000 位数字,这会导致大量子函数调用,并且我的程序无法计算结果,即使在我的计算机上也是如此。

问题如下: ACODE

我的解决方案如下:

import sys

def chk(word):
    if word[0] == '0':
        return 0
    if int(word) < 27 and int(word) > 0:
        return 1
    else:
        return 0

def dp(line):
    if len(line) > 2:
        return chk(line[0])*dp(line[1:]) + chk(line[:2])*dp(line[2:])
    elif len(line) > 1:
        return chk(line[0])*dp(line[1]) + chk(line)
    else:
        return chk(line)

line = sys.stdin.readline().strip()
while line != '0':
    print dp(line) 
    line = sys.stdin.readline().strip()

搜索互联网导致以下解决方案:

1) 用 0 和元素 0 初始化一个大小为 N 的数组为 1
2) 遍历所有元素
3) 如果是有效的个位数,将前一个元素的值复制到当前元素 (DP[i] = DP[i-1])
4)如果是有效的两位数,将前一个元素的值添加到当前元素(DP[i] += DP[i-2])

在一行中:DP[i] = DP[i-1] {如果有效的单个数字} + DP[i-2] {如果当前和以前的元素构成有效的两位数}

我不确定我是否在做同样的事情,因为我无法理解上述方法,或者是否有某种方式可以将我的递归方法转变为迭代。

【问题讨论】:

  • 没有做同样的事情。您的算法具有指数级运行时复杂性,因为您不会记住子问题的结果(而是一遍又一遍地重新计算它们)。
  • 在这种情况下如何记忆结果?
  • @KartikAnand 看看my answer 以获取 Niklas 建议的备忘录。
  • 你应该使用索引来表示你的字符串的前缀而不是字符串,否则即使你添加了memoization,你也可能会耗尽内存和时间。

标签: python algorithm dynamic-programming


【解决方案1】:

算法遵循动态规划方法。

它只是从左到右扫描代码字符串。

随着字符串长度的增加,可能性的数量也会增加。

每个新数字都有两种可能性。如果是有效数字,则新的可能性数量至少等于前一个数字之前的可能性。

另外,如果新数字和前一个数字组成 >= 11 和

Example if the number is 2134

A[0] = 1.
second digit is 1. Hence A[1] is at least = A[0] = 1. 
Also, 21 can make a valid character code as well. 
Hence, A[1] becomes 1 + 1 = 2.

The two strings possible upto A[1] are 2,1 and 21.

Third digit is 3. Hence A[2] is at least = A[1] = 2. 
Also, 13 can make a valid character code.
Hence additional possibilities can result if we consider 13 as a single character = A[2].
Hence A[3] = 2 + 1 = 3 ({2,1,3}, {21,3}, {2,13})

Simililarly for A[4].

【讨论】:

  • 是的,我可以看到,但我无法消化解决方案。能详细点吗?
  • 不是要更新其索引的数组 A,我不能只取一个计数变量吗?
  • @KartikAnand 在我们使用 DP[I-2] 计算 DP[I] 之前,您需要跟踪至少 2 个字符的计数。
  • 感谢您的解释
【解决方案2】:

2 个非常小的修改(不会提高效率,但更 Python 和更好)

def chk(word):
    if word[0] == '0':
        return 0
    elif 0 < int(word) < 27: # notice the elif & multiple comparisons
        return 1
    else:
        return 0

【讨论】:

  • 哦,我的错,肯定是一个非常糟糕的地方!已更新。
  • 最好不要复制字符串(这会增加另一个n 时间复杂度因素)。另外,你肯定会在这里耗尽内存,因为你无法在两次运行之间清除缓存。
  • 是的,像这样缓存它是一个非常糟糕的主意。需要不同的方法。
猜你喜欢
  • 2011-10-14
  • 2011-11-09
  • 2013-08-09
  • 2016-11-26
  • 1970-01-01
  • 2015-07-22
  • 2017-10-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多