日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

java动态规划凑硬币问题,详解动态规划最少硬币找零问题--JavaScript实现

發(fā)布時間:2025/3/21 javascript 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java动态规划凑硬币问题,详解动态规划最少硬币找零问题--JavaScript实现 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

硬幣找零問題是動態(tài)規(guī)劃的一個經(jīng)典問題,其中最少硬幣找零是一個變種,本篇將參照上一篇01背包問題的解題思路,來詳細(xì)講解一下最少硬幣找零問題。如果你需要查看上一篇,可以點擊下面鏈接:

詳解動態(tài)規(guī)劃01背包問題--JavaScript實現(xiàn)

下面讓我們開始吧。

問題

給定4種面額的硬幣1分,2分,5分,6分,如果要找11分的零錢,怎么做才能使得找的硬幣數(shù)量總和最少。

分析

最少硬幣找零問題,是為了求硬幣的組合,所以一個大前提是硬幣無限量供應(yīng)。我們建立如下表格來分析問題:

其中每列用j表示零錢總額,每行i表示硬幣面額。T[i][j]表示硬幣個數(shù),它是我們即將填入表格的數(shù)字。

在填寫表格之前,我們需要先明確幾個規(guī)則:

當(dāng)填寫第i行時,使用的硬幣面額僅能是i以及小于i的面額。舉個例子,比如我填寫第0行,i=0,那么這一樣只能使用面額為1分的硬幣。當(dāng)我填寫第2行,i=2,那么可以使用1分,2分,5分三種面額的硬幣。

當(dāng)填寫第j列時,表示當(dāng)前需要使用硬幣湊出的總額。比如j=6,表示需要使用硬幣組合出總額為6分的情況。

1. i = 0

當(dāng)我們只能使用面額為1分的硬幣時,根據(jù)上面的規(guī)則,那么很顯然,總額為幾分,就需要幾個硬幣。即T[i][j] = j。

2. i = 1

當(dāng)我們有1分和2分兩種面額時,那么組合方式就相對多了點。

i=1 j = 1:總額為1時,只能使用1分的面額。即填1。

i=1 j = 2:總額為2時,可以使用2個1分的,也可以使用1個2分的。因為我們要求最少硬幣,所以使用1個2分的。表格所表達(dá)的意思是硬幣的數(shù)量,所以這里也填1。

i=1 j = 3:總額為3時,可以使用3個1分的,也可以使用1個1分加1個2分。因此這里應(yīng)該填2。

i=1 j = 4:總額為4時,可以使用4個1分的,可以使用2個1分加1個2分,也可以使用2個2分。其中硬幣最少的情況應(yīng)該是2個2分。因此這里填2。

i=1 j = 5:總額為5時,組合就更多了,但是聰明的你應(yīng)該能想到使用2個2分加1個1分,可以實現(xiàn)最少硬幣的需求。因此這里填3。

我們來看填寫完上面5格后的情況:

建議你自己再紙上照著我這圖畫一個表格。接下來,別急著填表。我們要根據(jù)已有的數(shù)據(jù),總結(jié)出T[i][j]的規(guī)律,然后通過填寫剩余表格來驗證。

我們將硬幣面額使用數(shù)組coins[i]來表示,根據(jù)表格有 1分=coins[0], 2分=coins[1]。

當(dāng)j

當(dāng)j>=coins[i]時,根據(jù)已有的 i=1行可以推出一個規(guī)律,令a = 1+T[i][j-coins[i]],T[i][j]= min(T[i-1][j],a),即二者比較取最小值。可能一開始你看到這個關(guān)于a的公式,有點太突然,難以接受。稍微解釋一下,當(dāng)?shù)趇行,優(yōu)先選擇這一樣的硬幣,因為這一行的硬幣面額最大,最有可能使得總硬幣數(shù)量最少。因此j-coins[i],就很好理解了,就是選擇了這一行的硬幣后,還剩下多少總額。舉個例子,當(dāng)i=1,j=3時,j-coins[1]=1。那么選擇2分后,還剩余總額為1,這時候我們再定位到i=1,j=1,即T[1][1],它的值為1,再加上一個常數(shù)1,即得最終結(jié)果2。

再舉例,i=1 j=5。由于是從左到右填表的,所以i=1,j<5的表格都填完了。j-coins[i]=3,定位到T[1][3]=2,加上常數(shù)1,即得最后結(jié)果T[1][5]=3。

其實公式本身很短,也很好記。如果實在無法理解,建議先不用糾結(jié)。先最小化瀏覽器,不要看本篇剩余的內(nèi)容。帶著這個解題公式,自己在紙上,把這個表格填寫完整,在填表分析的過程中就能慢慢理解了。

3. 剩余內(nèi)容

按照上一步所提供的公式,其實所有的T[i][j]都可以填完了。如下表格。

建議先自己再紙上填表,填完了,再和我的圖對比一下,看是否答案存在出入。

4.偽代碼

以上的填表邏輯,使用偽代碼表示如下

if(i == 0){

T[i][j] = j/coins[i]; //硬幣找零一定要有個 最小面額1,否則會無解

}else{

if(j >= coins[i]){

T[i][j] = min(T[i-1][j],1+T[i][j-coins[i]])

}else{

T[i][j] = T[i-1][j];

}

}

復(fù)制代碼

5. 尋找組合

至此,填完表格我們已經(jīng)接近完成了。接下來要尋找從表格中尋找硬幣組合。🤔

與填表順序相反,尋找組合從有下角開始。

首先需要明確的是如果T[i][j] == T[i-1][j],那么就向上搜索。根據(jù)圖來分析:

1. 定位到T[3][11] ,由于不存在T[i][j] == T[i-1][j],所以不用向上搜索,確定選中一個6分硬幣。尋找組合的思路和填寫T[i][j]的思路幾乎是反過來的。

2. 選擇一個6分硬幣后,剩余的總額為11-6=5。因此定位到T[3][5]中。由于T[3][5]==T[2][5],因此看圖中的藍(lán)色箭頭,向上搜索,直到T[i][j] != T[i-1]。

3. 定位到T[2][5]中,此時coins[i]為5分。選中5分硬幣只有,剩余的總額為5-5=0。

4. 當(dāng)j=0時,搜索結(jié)束。由上面步驟確定選中的硬幣組合為:1個5分,1個6分。

代碼

以上就是整個最少硬幣找零問題的分析思路。最終代碼使用 JavaScript 實現(xiàn),如果你的 Sublime 支持純 JavaScript,你可以直接復(fù)制黏貼代碼,command + b 直接運行查看結(jié)果,然后修改輸入變量,查看更多情況下的輸出結(jié)果。

//動態(tài)規(guī)劃 -- 硬幣找零問題

function minCoins(coins,total,n){

var T = [];

for(let i = 0;i

T[i] = []

for (let j=0;j<= total;j++){

if(j == 0){

T[i][j] = 0;

continue;

}

if(i == 0){

T[i][j] = j/coins[i]; //硬幣找零一定要有個 最小面額1,否則會無解

}else{

if(j >= coins[i]){

T[i][j] = Math.min(T[i-1][j],1+T[i][j-coins[i]])

}else{

T[i][j] = T[i-1][j];

}

}

}

}

findValue(coins,total,n,T);

return T;

}

function findValue(coins,total,n,T){

var i = n-1, j = total;

while(i>0 && j >0){

if(T[i][j]!=T[i-1][j]){

//鎖定位置,確定i,j值,開始找構(gòu)成結(jié)果的硬幣組合。 其實根據(jù)這種計算方法,只需要考慮最右邊那一列,從下往上推。

//console.log(T[i][j]);

break

}else{

i--;

}

}

var s = []; //存儲組合結(jié)果

while(i >= 0 && j > 0 ){

s.push(coins[i]);

j=j-coins[i];

if(j <= 0){

break; //計算結(jié)束,退出循環(huán)

}

//如果 i == 0,那么就在第 0 行一直循環(huán)計算,直到 j=0即可

if(i>0){

//console.log(i);

while(T[i][j] == T[i-1][j]){

i--;

if(i== 0){

break;

}

}

}

}

console.log(s);

//可以把數(shù)組s return 回去

}

var coins = [1,2,5,6];

var total = 11

var n = coins.length

console.log(minCoins(coins,total,n));

復(fù)制代碼

總結(jié)

以上是生活随笔為你收集整理的java动态规划凑硬币问题,详解动态规划最少硬币找零问题--JavaScript实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。