2015-05-06 73 views
2

我的老師給了我一套問題,讓我們考慮遞歸。其中之一,我們被賦予一個價值(郵資的成本)和一個可用的郵票列表。該練習涉及編寫一個遞歸函數,該函數返回郵票的最小長度列表,其總數等於郵資的總和值。郵票拼圖

解決這個問題的正確方法就是讓程序比較每一種可能性並返回最小長度的程序。如果是這種情況,我不確定如何爲它編寫程序,更不用說使用遞歸,因爲我一般都是Python和編程的新手。根據教師提供的線索,我想出了這樣的事情:

stampList=[1,4,7] 
postage=10 

def pickStamps(postage): 
    if postage==0: #base case 1 
     return "" 
    if postage<0: #base case 2 
     return none 
    else: 
     x=postage 
     for i in range(len(stampList)-1): 
     x=x-stampList[i] 
     return pickStamps(x) 

我試圖有蟒蛇開始郵資的價值,減去結合每種面額才能到零,但我不確定如何將每種可能性都列入清單。在問題中提出,編寫另一個函數可能是明智的,該函數接受一個列表列表的參數,並返回列表中最小長度元素的索引,但我不確定如何實現該列表。有人能告訴我如何編寫這樣的代碼或解釋解決這個問題的最佳方法嗎?謝謝!

+4

這是算法類嗎?你被要求做動態編程嗎?貪婪算法並不總能給你正確的答案 – inspectorG4dget

+2

這是一個有趣的鏈接,瞭解動態編程和記憶http://interractivepython.org/runestone/static/pythonds/Recursion/DynamicProgramming.html – Scott

回答

0

試想一下,你有已經工作的功能:

def pick_stamps(postage): 
    '''Returns list of stamps needed to cover postage''' 

鑑於你有這個功能,你可以用它來實現您的版本:

def my_pick_stamps(postage): 
    if postage == 0: 
     return [] 
    else: 
     stamp = max(stamp for stamp in stamps 
        if stamp <= postage) 
     return [stamp] + pick_stamps(postage - stamp) 

當然,一旦你實現你可以使用你的版本,並用my_pick_stamps代替pick_stamps

+1

感謝您的迴應!你能解釋一下這兩項計劃是如何協同工作的嗎?我不太擅長閱讀代碼,但是如果我將最後一個pick_stamps更改爲my_pick_stamps,看起來好像您的代碼可以自行工作。 – 88jerry88

+0

@ 88jerry88確切地說,這是遞歸的一點。你假設你有一個可行的功能,然後用它來解決一個較小的問題,這就是整個問題。 –

1
def ways(wallet, stamp_values, postage): 
    amount = sum(wallet) 
    if amount == postage: 
     return [wallet] 
    elif amount > postage: 
     return [] 
    else: 
     next_stamp = wallet[-1] if wallet else max(stamp_values) 
     new_stamps = stamp_values[stamp_values.index(next_stamp):] 
     gen = (ways(wallet + [c], new_stamps, postage=postage) for c in new_stamps) 
     return sum(gen, []) 

試駕:

>>> combos = ways([], stamp_values=(7,4,1), postage=10) 
>>> combos 
[[7, 1, 1, 1], 
[4, 4, 1, 1], 
[4, 1, 1, 1, 1, 1, 1], 
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] 
>>> min(combos, key=len) 
[7, 1, 1, 1] 

注意該解決方案實際上是在你的例子非唯一,即7,1,1,1和4,4,1,1都是相同的長度。假設我們有一個價值3的新郵票,我們應該期望看到一個獨特的解決方案,然後(7 + 3 == 10與兩個郵票)。

>>> ways([], stamp_values=(7,4,3,1), postage=10) 
[[7, 3], 
[7, 1, 1, 1], 
[4, 4, 1, 1], 
[4, 3, 3], 
[4, 3, 1, 1, 1], 
[4, 1, 1, 1, 1, 1, 1], 
[3, 3, 3, 1], 
[3, 3, 1, 1, 1, 1], 
[3, 1, 1, 1, 1, 1, 1, 1], 
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] 
+0

感謝您的回覆。它似乎工作正常,直到我測試它爲50.它給了我11,11,11,11,1,1,1,1,1,1而不是40,7,1,1,1。是否得到相同的迴應? – 88jerry88

+0

它對我使用'ways([],stamp_values =(40,7,4,1),郵資= 50)'正確工作。請注意,我的算法期望'stamp_values'從高到低排序。如果你願意,很容易去除這個限制,我會把它作爲一個練習。 – wim

+0

啊我之前沒有注意到這個限制,謝謝。另外,作爲一個附註,我還沒有看到if和else之後沒有:和indentation之後,你能否認爲它們是如何在你的代碼中工作的?謝謝! – 88jerry88