動態規劃 砝碼稱重問題

2021-08-09 23:48:43 字數 3666 閱讀 2521

一、演算法分析

動態規劃(dynamic programming)這個詞乍一聽感覺甚是高大上,初次學習或者使用的時候會感覺難以理解,這是正常的,畢竟凡事都是一回生二回熟。其實它也不難的,大家要明白乙個道理,能寫到課本上給學生學習的東西必然屬於不難的東西,因為太難的東西寫到課本上讀者接受不了,這本書就沒有出版的意義了。當然我說的不難也僅僅只是說動態規劃的思想不難,因為我們常常面臨著乙個棘手的問題---那就是這個理論應用到實踐中的時候,它沒有乙個公式或者現成的可以直接用來套用的模型。對於這一點,沒有辦法,只能是通過多種案例,自己多總結,多思考,看看每一種能用動態規劃理論解決的問題,狀態模型究竟是如何建立的,而這就需要讀者多多練習了。

本文通過華為oj上乙個基本題-砝碼稱重問題來讓初學者消化動態規劃。

先來讀一讀題目,題目如下:

現有一組砝碼,重量互不相等,分別為m1、m2……mn;他們可取的最大數量分別為x1、x2……xn。現在要用這些砝碼去稱物體的重量,問能稱出多少種不同的重量。

看完這個題目感覺似乎無從下手,難道要乙個個的列舉拼湊嗎?答案是否定的。不繞彎子了,下面直接進入動態規劃的主場。我們假定砝碼的重量單位是克,下文中不新增這個單位,只說數字,比如重量是1,表示重量是1克。

設想第0種情況,假如現在只有0個砝碼,問它能稱出的重量有幾種?是個人都知道只能稱0的重量,並且只有這麼1種情況。

設想第1種情況,現在只有1種規格的砝碼,它的重量是1,數量是1個,問它能稱出的重量有幾種?很明顯,能稱出0和1這2種重量,一共2種情況。

設想第2種情況,現在有2種規格的砝碼,它們的重量分別是1和2,1克的砝碼1個,2克的砝碼1個,問它能稱出的重量有幾種?用手比劃比劃應該能知道,能稱出0,1,2,3這4種重量,4種情況。

。。。。。。

設想第n種情況,現在有n種規格的砝碼,他們的重量分別為m1,m2。。。mn,問它能稱出的重量是幾種?這個時候貌似不是用手比劃比劃就可以出來結果了。但是這個問題的提出,就相當於是題目最終要解決的問題了。如果能夠利用某種規律回答這第n種情況的提問,那麼砝碼稱重的問題就可以完全解決。問題來了,上面的分析過程是否存在乙個規律呢?答案是規律肯定存在,並且分析這種規律的思路就是動態規劃的思路。

現在我們把第n種情況能稱出的重量種數用f(n)來表示,可以試著這樣具體化的描述,第0種情況能稱出的重量有f(0)種,第1種情況能稱出的重量有f(1)種,第2種情況能稱出的重量有f(2)種,。。。第n種情況能稱出的重量有f(n)種。

下面,回歸到上面的提到的情況分析中去。

第0種情況,f(0)=1;

第1種情況,f(1)=2;如果把這個結果和第0種情況結合起來看,可以認為:f(1)=f(0)+1,此式意義非凡,它的意義為:第1種情況可以建立在第0種情況的基礎上去解決,單單來看情況1的砝碼可以稱1種重量(即用乙個1克的砝碼稱1克的物體)不同於情況0中,二者相加即為f(1)的結果。

第2種情況,f(2)=4=f(1)+2,為什麼加2?因為如果僅僅只有1個1克的砝碼和1個2克的砝碼,它只能稱出重量為2克,3克這兩種不同於情況1中的重量(情況1中已經解決了0克和1克的問題)。

現在假定已經解決了第n-1種情況,即f(n-1)的值已經知道,那麼我們如果能計算出單單第n種情況能稱出哪些不同於n-1種情況中的重量,假定為x種,那麼f(n)=f(n-1)+x。最終問題便得到了解決。

請仔細領會上面的這個分析過程,一定要弄明白。

下面附上c++的程式,本程式先計算第0種砝碼能稱出多少種重量,能稱出的重量均在flag[100000]陣列中做好標記,然後計算第0種砝碼最多能稱多大的重量,在這個基礎上加入第1種砝碼,然後計算第2種,直至第n種。程式最關鍵的地方在於29行採用currentweight逐次加1試探的方式得到乙個數值,然後在33行驗證這個currentweight是否是前一種情況中的砝碼可以稱出來的重量,如果是,表明新的重量值確實可以稱出來,那麼就把這個重量在flag[100000]陣列中標記。最後統計標誌陣列flag[100000]種1的次數,即為所有砝碼隨意組合可以稱出的重量。

二、參考**

#include

#include

#include

using namespacestd;

intfama(intn, intweight, intnum)

;

/*先計算第0種砝碼能夠得到的稱重數量,並且計算第0種砝碼最大的重量*/

inttempweight=0;

for (i=0;i<=num[0];i++)

tempweight=weight[0]*num[0];

//從此以後tempweight將用來表示前一種砝碼的最大重量  

i=1;//從第1種砝碼開始做  

intcurrentweight;

intnewweight;

while (i<n)

}

}

tempweight=tempweight+num[i]

*weight[i];//更新上乙個砝碼的最大重量  

i++;

}

/*統計總數量*/

intcount=0;

for (i=0;i<1000;i++)

returncount;

}

intmain()

動態規劃 砝碼稱重問題

動態規劃 dynamic programming 這個詞乍一聽感覺甚是高大上,初次學習或者使用的時候會感覺難以理解,這是正常的,畢竟凡事都是一回生二回熟。其實它也不難的,大家要明白乙個道理,能寫到課本上給學生學習的東西必然屬於不難的東西,因為太難的東西寫到課本上讀者接受不了,這本書就沒有出版的意義了...

動態規劃 砝碼稱重

問題描述 設有1g,2g,3g,5g,10g,20g的砝碼各若干枚 其總重 1000g 要求 輸入 a1 a2 a3 a4 a5 a6 表示1g砝碼有a1個,2g砝碼有a2個,20g砝碼有a6個 輸出 total n n表示用這些砝碼能稱出的不同重量的個數,但不包括乙個砝碼也不用的情況 輸入樣例 1...

動態規劃 砝碼稱重

砝碼稱重問題 設有1g 2g 3g 5g 10g 20g 的砝碼各若干枚 其質量 1000g 求出用他們能稱出的質量的種類數 不包括質量為0的情況 設dp 1000 陣列為標記陣列。當dp 0時,表示質量為i的情況,目前沒有稱出 當dp 1時,表示質量為i的情況已經稱出。本題目中有多個砝碼,我們順序...