Python3算法實(shí)例 1.2:動(dòng)態(tài)規(guī)劃 之 換零錢

money.jpg
問題(基礎(chǔ)版):

把100元兌換成1元,2元桩引,5元缎讼,10元,20元坑匠,50元的零錢血崭,共有多少種不同換法。

動(dòng)態(tài)規(guī)劃思想解析:
  • 拆解子問題
    下面以5元換成1,2,3元的零錢為例厘灼。T[(change),target]表示用零錢序列change組成target的所有方法夹纫。見下圖:
    example.png

其中:
T1[(1,2),5-0*3]可看作只用1和2元设凹、不用3元組成5元的方法數(shù)舰讹;
T2[(1,2),5-1*3]可看作用1和2元闪朱、并且只用1個(gè)3元組成5元的方法數(shù)月匣;
T6[(1),3]可看作用1元奋姿,只用1個(gè)2元锄开、并且不用3元組成5元的方法數(shù);
T9[(1)称诗,0]可看作用1元院刁,只用1個(gè)2元只用1個(gè)3元組成5元的方法數(shù)粪狼。

  • 狀態(tài)轉(zhuǎn)移表達(dá)式:


    problem.png
  • 邊界條件:
    • M-nd不得小于0退腥,并且當(dāng)M-nd等于0時(shí)任岸,也就是說之前的選擇已經(jīng)組成了目標(biāo),所以表達(dá)式結(jié)果為1狡刘。
    • 如果表達(dá)式為T[(a),c]享潜,只有a可以被c整除,此表達(dá)式才為1嗅蔬,否則為0剑按。例如T[(2),5]=0,T[(2),6]=1。
Python3程序?qū)崿F(xiàn)
#遞歸實(shí)現(xiàn)
#根據(jù)邊界條件編寫程序
def Solve(exlist,target):
    #判斷問題解
    if target==0:
        return 1
    else:
        if len(exlist)==1 and target%exlist[0]==0:
            return 1
        else:
            return 0

#遞歸的方式澜术,先將問題拆解為子問題的集合 
def Dismantle(exlist):
    if len(exlist[0][0])>1:
        fu=[]
        for ie in exlist:
            for ji in range(int(ie[1]/ie[0][-1])+1):
                fu.append([ie[0][0:-1],ie[1]-ji*ie[0][-1]])
        return Dismantle(fu)
    else:
        return exlist

#計(jì)算結(jié)果
def Recursion(exlist,target):
    structer=[[exlist,target]]
    count=0
    for jj in Dismantle(structer):#所有子問題的集合
        if Solve(jj[0],jj[1])==1:#計(jì)算每一個(gè)子問題的結(jié)果
            count+=Solve(jj[0],jj[1])
    return count

print(Recursion([1,2,5,10,20,50],100))
結(jié)果:4562

上述的遞歸程序編寫較為復(fù)雜艺蝴,但是容易理解,下面給出基于動(dòng)態(tài)規(guī)劃的程序鸟废。

#動(dòng)態(tài)規(guī)劃實(shí)現(xiàn)
def DP_Com(exlist,num):
    an=[1]+[0]*num
    for i in exlist :
        for j in range(i,num+1):
            an[j]+=an[j-i]
    return an[num]
print(DP_Com([1,2,5,10,20,50],100))
結(jié)果:4562
問題(進(jìn)階版):

有面值為1元猜敢、3元和5元的錢幣若干張,如何用最少的錢幣湊夠11元盒延,并列出組合方法缩擂。

拆解子問題:

和基礎(chǔ)版問題相比,此題復(fù)雜之處在于最小值的計(jì)算添寺。詳細(xì)見下圖:

min.png
Python3程序?qū)崿F(xiàn)
#記錄
def DP_Min(exlist,target):
    fan=[0]+[target]*target
    record=['']*(target+1)
    #存儲(chǔ)最后一位
    lic=[]
    for i in exlist:
        for j in range(i,target+1):
            if fan[j-i]!=target:#如果等于target胯盯,說明之前沒有數(shù)的結(jié)合可以達(dá)到這個(gè)數(shù)
                fan[j]=min(fan[j-i]+1,fan[j])
                #記錄
                if fan[j-i]+1<=fan[j]:
                    record[j]=record[j-i]+'%d*'%i
                else:
                    record[j]=record[j]
        if record[-1]!='':
            lic.append(record[-1])
    if len(lic)==0:
        return '無解'
    else:
        return lic,fan[target]

#處理字符串
def Handle(exstr,num):
    for i in set(exstr):
        hu=i.split('*')
        hu=list(filter(lambda x:x,hu))#去除掉split留下的空格
        if len(hu)==num:
            shuoming=''
            for j in set(hu):
                shuoming+='%s個(gè)%s '%(hu.count(j),j)
            print(shuoming)
    return 'Done'

ggg=DP_Min([1,3,5],11)
print(Handle(ggg[0],ggg[1]))
#結(jié)果:最少為3。組合方法:2個(gè)5 1個(gè)1 

不定期更新计露,歡迎留言博脑,敬請(qǐng)關(guān)注!!!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市票罐,隨后出現(xiàn)的幾起案子趋厉,更是在濱河造成了極大的恐慌,老刑警劉巖胶坠,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件君账,死亡現(xiàn)場離奇詭異,居然都是意外死亡沈善,警方通過查閱死者的電腦和手機(jī)乡数,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來闻牡,“玉大人净赴,你說我怎么就攤上這事≌秩螅” “怎么了玖翅?”我有些...
    開封第一講書人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我金度,道長应媚,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任猜极,我火速辦了婚禮中姜,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘跟伏。我一直安慰自己丢胚,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開白布受扳。 她就那樣靜靜地躺著携龟,像睡著了一般。 火紅的嫁衣襯著肌膚如雪勘高。 梳的紋絲不亂的頭發(fā)上峡蟋,一...
    開封第一講書人閱讀 49,784評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音相满,去河邊找鬼。 笑死桦卒,一個(gè)胖子當(dāng)著我的面吹牛立美,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播方灾,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼建蹄,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了裕偿?” 一聲冷哼從身側(cè)響起洞慎,我...
    開封第一講書人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嘿棘,沒想到半個(gè)月后劲腿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鸟妙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年焦人,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片重父。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡花椭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出房午,到底是詐尸還是另有隱情矿辽,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站袋倔,受9級(jí)特大地震影響雕蔽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜奕污,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一萎羔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧碳默,春花似錦贾陷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至该抒,卻和暖如春慌洪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背凑保。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國打工冈爹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人欧引。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓频伤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親芝此。 傳聞我的和親對(duì)象是個(gè)殘疾皇子憋肖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容