【问题标题】:Dynamic programming for primitive calculator原始计算器的动态规划
【发布时间】:2016-08-24 03:04:06
【问题描述】:

我正在处理这个问题,这与找硬币问题非常相似。

我需要实现一个简单的计算器,它可以对当前数字 x 执行以下三个操作:将 x 乘以 2、将 x 乘以 3 或将 x 加 1。

目标给定一个正整数n,从数字1开始求得到数字n所需的最少操作次数。

我对此采取了一种贪婪的方法,但它显示的结果不正确

import sys

def optimal_sequence(n):
    sequence = []
    while n >= 1:
        sequence.append(n)
        if n % 3 == 0:
            n = n // 3
        elif n % 2 == 0:
            n = n // 2
        else:
            n = n - 1
    return reversed(sequence)

input = sys.stdin.read()
n = int(input)
sequence = list(optimal_sequence(n))
print(len(sequence) - 1)
for x in sequence:
    print(x)

例如:

Input: 10
Output: 
4
1 2 4 5 10

4 步。但正确的是 3 个步骤:

Output: 
3
1 3 9 10

我阅读了有关动态编程的内容,希望可以在这里实现它。但是,在特定情况下我无法正确使用它,有人可以给我建议吗?

【问题讨论】:

标签: python dynamic-programming greedy


【解决方案1】:

只需通过简单的递归和Memoization来解决它:

代码:

d = {}

def f(n):
    if n == 1:
        return 1, -1
    if d.get(n) is not None:
        return d[n]
    ans = (f(n - 1)[0] + 1, n - 1)

    if n % 2 == 0:
        ret = f(n // 2)
        if ans[0] > ret[0]:
            ans = (ret[0] + 1, n // 2)

    if n % 3 == 0:
        ret = f(n // 3)
        if ans[0] > ret[0]:
            ans = (ret[0] + 1, n // 3)

    d[n] = ans
    return ans

def print_solution(n):
    if f(n)[1] != -1:
        print_solution(f(n)[1])
    print n,

def solve(n):
    print f(n)[0]
    print_solution(n)
    print ''

solve(10)

提示:f(x) 返回一个元组 (a, b),其中a 表示从 1 得到 x 的最小步骤,b 表示获得最优解的前一个数。 b 仅用于打印解决方案。

输出:

4 # solution for 10
1 3 9 10 

7 # solution for 111
1 2 4 12 36 37 111

您可以调试我的代码并了解它是如何工作的。如果您是 DP 的初学者,您可以阅读我的另一篇关于 DP 的SO post 以快速入门。


由于Python不能递归很多(大约10000),所以我写了一个迭代版本:

# only modified function print_solution(n) and solve(n)

def print_solution(n):
    ans = []
    while f(n)[1] != -1:
        ans.append(n)
        n = f(n)[1]
    ans.append(1)
    ans.reverse()
    for x in ans:
        print x,

def solve(n):
    for i in range(1, n):
        f(i)[0]
    print_solution(n)
    print ''

solve(96234) # 1 3 9 10 11 22 66 198 594 1782 5346 16038 16039 32078 96234 

【讨论】:

  • 这里有一个问题,而不是最后一行的solve(10),如果你解决了(96234),它会抛出堆栈溢出错误。如何克服这个@Sayakiss?请告诉我..
  • @KishanB Python程序不能递归很多...我给你写一个迭代...
  • "ans = (f(n - 1)[0] + 1, n - 1)" 中的外括号是什么意思?
  • @BrunoNegrãoZica f(n) 返回(a, b),所以f(n)[0] 是(a, b) 的a。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-29
  • 1970-01-01
  • 2018-05-11
  • 1970-01-01
  • 2012-03-26
相关资源
最近更新 更多