程式設計之美之買書問題

2021-06-22 12:36:23 字數 3536 閱讀 8452

關於程式設計之美中買書的問題,我困擾了好久。當然,我的數學能力不強,領悟能力又差,所以才困擾了這麼久。不過,在本人的堅持下,終於理解透徹。為了記住這一時刻,更為了免除以後忘記的可能,暫時記錄如下。

書中關於證明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冊 那麼最優打折方式就是 分兩次購買,一本一冊,一本二冊,一本三冊和一本四冊,然後就是剩下的書籍 ...