簡體   English   中英

遞歸給出最小硬幣找零的正確答案,但動態編程給出錯誤答案

[英]Recursion gives correct answer for minimum Coin Change but dynamic programming gives wrong answer

我試圖解決這個問題已經有好幾個小時了,但是我不能直覺地考慮它。 關於它有某種精神障礙。 經過多次嘗試,對於存在解決方案的情況,我能夠獲得正確的遞歸解決方案。 所以我有以下問題:

  1. 遞歸程序為存在解決方案的輸入提供正確的解決方案。 如何在不存在解決方案的地方返回“不存在解決方案”。 例如,對於硬幣[3,10],不存在用於更改17的解決方案。

  2. DP程序有什么錯誤? 我嘗試使用記憶技術來創建字典並向其中添加值,但是該程序無法正常運行。

import math
def findMinCoins(denomination, change):
    #recursive solution
    minCoins = change
    if(len(denomination )== 0 or change ==0): #when there are no coins or change is 0
        return 0
    elif(change in denomination):
        return 1
    elif(change < min(denomination)):
        return float("inf")
    else:
        for i in denomination:
            if(i<=change):
                numCoins = 1 + findMinCoins(denomination, change - i)
                if(numCoins < minCoins):
                    minCoins = numCoins
    return minCoins

c = [3,10]
d = 30

print findMinCoins(c,d)

現在這里是DP解決方案。

import math
coinsDict = {}

def findMinCoins(denomination, change):
    minCoins = change
    if(len(denomination )== 0 or change ==0):
        return 0
    elif(change in denomination):
        return 1
    elif(change < min(denomination)):
        return float("inf")
    else:
        for i in denomination:
            if (coinsDict.get(change)):
                print 'dictionaty',change, coinsDict.get(change)
                return coinsDict[change]
            elif(i<=change):
                numCoins = 1 + findMinCoins(denomination, change - i)
                if(numCoins < minCoins):
                    minCoins = numCoins
                    print change, numCoins
                    coinsDict[change] = numCoins

    return minCoins

c = [3,10]
d = 30

print findMinCoins(c,d)

問題出在使用備忘錄的方式上。 如果您找到了針對特定數量變更的解決方案,那么您永遠不會認為有更好的解決方案。 看邏輯

    if (coinsDict.get(change)):
        print 'dictionaty',change, coinsDict.get(change)
        return coinsDict[change]
    elif(i<=change):
        numCoins = 1 + findMinCoins(denomination, change - i)

在第一次遞歸過程中,您一直走下去,發現可以用10枚3枚硬幣來處理30美分。然后您退回到堆棧頂部,然后再嘗試10枚硬幣。但是在您不願尋找解決方案之前,上述邏輯就說:“我已經知道如何處理30美分:退回10個硬幣。” 探索涉及其他金額的解決方案永遠是不可能的。

如果顛倒了檢查面額的順序,您將獲得所需的解決方案。 確保您嘗試其他測試用例:您應該發現這種簡單的修復不足以修復您的邏輯。 例如,嘗試

c = [3,11,13] d = 22

如果您找不到更好的解決方案,則會找到13、3、3、3的4硬幣解決方案,而錯過了11、11的答案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM