關於程式設計之美中買書的問題,我困擾了好久。當然,我的數學能力不強,領悟能力又差,所以才困擾了這麼久。不過,在本人的堅持下,終於理解透徹。為了記住這一時刻,更為了免除以後忘記的可能,暫時記錄如下。
書中關於證明f(y1-1,y2-1,y3-1,y4-1,y5)和f(y1-1,y2-1,y3-1,y4,y5-1)的等價性,作者舉了乙個例子,y1=y2=y3=y4=y5=2。但我認為,這個例子太過特殊,因為每卷本的數量都是相同的,顯然只要調整後兩項的順序,(y1-1,y2-1,y3-1,y4-1,y5)和(y1-1,y2-1,y3-1,y4,y5-1)的序列便是完全一樣的,這個是很好理解的,根本不需要再進行多餘的解釋。但是如果y4和y5不相等的話,就需要多解釋一下了。我想,作者真是企**釋這種情況,但是卻用了乙個特殊的不用多做解釋的例子。其次,我想,除了完全歸納法之外,通過舉具體例子的方式去證明乙個抽象的問題是不足的。那麼應該如何證明呢?
其實,我也不知道怎麼證明才好,只能根據自己的理解做一下邏輯推理,當然這個推理基於書中的推理但又做了延伸。讓我們來看(y1-1,y2-1,y3-1,y4,y5-1)這個序列,由於y4>=y5, 所以y4>y5-1,那麼在最後的最優解中,一定會出現只有y4卷而沒有y5卷的一組(至少一組,可能多組,根據y4和y5的相對大小和最優解的分配情況)。那麼把這個只有y4卷而沒有y5卷的一組(只是一組,而不是多組,我想這一點書中作者沒有說明清楚)中的y4卷換成y5卷後,得到的仍是同樣的解,但是由於整體上看,y4卷少了一本,y5卷多了一本,這正是(y1-1,y2-1,y3-1,y4-1,y5)的序列。這時,可以回歸書中的一句話(y1-1,y2-1,y3-1,y4,y5-1)的最優解必是(y1-1,y2-1,y3-1,y4-1,y5)的乙個解,因此只要求出(y1-1,y2-1,y3-1,y4-1,y5)的最優解就好。
好了,對書中的這個內容作了補充解釋之後,再來個宣告:以上的推理也好,解釋也好,都是以書中的解釋為基礎,加以引申的,也許不應該叫半原創吧。
#!/usr/bin/env python
import random
def getminprice(books):
books.sort()
books.reverse()
if books[0] <= 0:
return 0,
prices =
paths =
if books[4] >= 1:
price,path = getminprice([books[0]-1,books[1]-1,books[2]-1,books[3]-1,books[4]-1])
if books[3] >= 1:
price,path = getminprice([books[0]-1,books[1]-1,books[2]-1,books[3]-1,books[4]])
if books[2] >= 1:
price,path = getminprice([books[0]-1,books[1]-1,books[2]-1,books[3],books[4]])
if books[1] >= 1:
price,path = getminprice([books[0]-1,books[1]-1,books[2],books[3],books[4]])
if books[0] >= 1:
price,path = getminprice([books[0]-1,books[1],books[2],books[3],books[4]])
minprice = min(prices)
i = prices.index(minprice)
minpath = paths[i]
minpath.insert(0,len(prices)-i)
return minprice,minpath
def getminbookprice(books):
assert(type(books) == list)
assert(len(books) == 5)
for i in books:
assert(type(i) == int)
return getminprice(books)
def getminbookprice2(books):
assert(type(books) == list)
assert(len(books) == 5)
for i in books:
assert(type(i) == int)
path =
count5 = 0
count3 = 0
while books[0] > 0:
books.sort()
books.reverse()
if books[4] >= 1:
books = [books[0]-1,books[1]-1,books[2]-1,books[3]-1,books[4]-1]
count5 += 1
elif books[3] >= 1:
books = [books[0]-1,books[1]-1,books[2]-1,books[3]-1,books[4]]
elif books[2] >= 1:
books = [books[0]-1,books[1]-1,books[2]-1,books[3],books[4]]
count3 += 1
elif books[1] >= 1:
books = [books[0]-1,books[1]-1,books[2],books[3],books[4]]
else:
books = [books[0]-1,books[1],books[2],books[3],books[4]]
if count5 > 0 and count3 > 0:
path.remove(5)
path.remove(3)
count5 -= 1
count3 -= 1
path.sort()
path.reverse()
price = 0
for i in path:
if i == 5:
price += 5*8*(1-0.25)
elif i ==4:
price += 4*8*(1-0.2)
elif i == 3:
price += 3*8*(1-0.1)
elif i == 2:
price += 2*8*(1-0.05)
else:
price += 8
return price,path
if __name__ == '__main__':
books = [random.randint(1,7) for i in range(5)]
print getminbookprice(books)
print getminbookprice2(books)
getminbookprice是歸併法,getminbookprice2是貪婪法的修正實現,我發現測試了幾次兩個方法的結果是一致的。不過還是那句話,舉例不足以證明貪婪法的修正實現的正確性。
《程式設計之美》之買書問題
這兩天剛看 程式設計之美 裡面的一些演算法有些確實經典,非常的感興趣,很喜歡自己先思考一下,然後看看書上的解析。對於1.4節的買書的問題,原書的解法二我看得不是很明白,而且解法一通過區域性最優解得到全域性最優解,這個肯定是不可取的,以下是我個人對這個問題的解法。本數 2 折扣 5 本數 3 折扣 1...
程式設計之美 買書問題
今天小夥伴在群裡給出了一道題 分享一道題,有興趣的可以做做哈。假設 冰與火之歌 有五卷,每一捲單獨買是20塊。兩卷連買減5 三卷連買減10 四卷連買減20 五卷連買減25 買相同的卷不打折。比如買兩本卷一,一本卷二,總 是58元。現買了一批書n,計算出它的最低 一看到這道題,瞬間就覺得這麼簡單有什麼...
買書問題 程式設計之美1 4
買書問題,如果一種書籍五冊,單獨買一冊8元,買兩冊不同的打95折,買三冊不同的書籍9折,買四冊不同的書籍8折,買五冊不同書籍75折,問怎麼買書最便宜。比如買2本一冊,2本2冊,2本三冊,1本4冊,1本5冊 那麼最優打折方式就是 分兩次購買,一本一冊,一本二冊,一本三冊和一本四冊,然後就是剩下的書籍 ...