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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

零钱组合

發布時間:2024/9/30 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 零钱组合 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.



給定面值為1,5,10,20,50的零錢,給定一個金額A,求組合成A的方法的數量

假定一個面額為x,則組合為A的方法數目 = 不使用x面額的零錢組合成A的方法的數量 + 使用任何面值的零錢組合成A -x的方法的數量

可以看成兩類,一類是沒有面額x而組合成A的數量,另一類是至少用一張面值為x而組合成A的方法的數量


直接按照算法的描述,遞推關系應該是:
nway[v][n]=nway[v-1][n]+nway[v][n-coin[v]];

面額存儲為coin= {1,5,10,20,50},下標為v,給定的金額為n

使用任何0-v面額的零錢,組合成n的方法數量 = 使用任何0-(v-1)面額的零錢組合成n的方法數量 + 使用任何0-v面額零錢組合成n-coin[v]的數量

動態規劃的遞推式

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

nway[0][i] = 1;//只用一種面額的零錢,對于任何N,方法都只有一種

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

nway[i][0] = 1;//如果N=0,方法也只有一種,就是不出任何零錢

for(v=1;v<5;++v)

{

for(n = coin[v];n<=N;++n)

{

nway[v][n]=nway[v-1][n]+nway[v][n-coin[v]];

}

}


由于nway[v-1][n]只會用一次,所以可以合并nway[v][n]=nway[v-1][n]


nway[0] = 1

for(v=0;v<5;++v)

for(n = coin[v];n<=N;++n)

nway[n] +=nway[n-coin[v]];//(可以擴展為nway[n] = nway[n] + nway[n-coin[v]])其中第二個nway[n]可以看做是當v-1時的方法數目


由題目可知,coin可以是任何順序,結果不變


//

上面的思路沒錯,但是程序寫錯了

解法1:可以出來金額為12,16這樣的不能完全湊整的

const int N = 45;//錢總數 const int K = 2;//錢的種類 int main() {int nway[K][N+1];memset(nway,0,sizeof(nway));int coin[]= {5,10};int i;for(i=coin[0];i<=N;++i)nway[0][i] = 1;//只用一種面額的零錢,對于任何N,方法都只有一種for(i=0;i<K;++i)nway[i][0] = 1;//如果N=0,方法也只有一種,就是不出任何零錢for(int v=1;v<K;++v){for(n = coin[v];n<=N;++n){nway[v][n]=nway[v-1][n]+(nway[v][n-coin[v]]?nway[v][n-coin[v]]:1);}}//cout<<nway[1][11]<<endl;cout<<nway[K-1][N]<<endl;return 0;}
解法2:貌似這個更容易理解


int nway[N+1];memset(nway,0,sizeof(nway));int coin[]= {5,10,20};nway[0] = 1;for (int i=0;i<K;++i){for (int v =coin[i];v<=N;++v){nway[v] = nway[v] + (nway[v-coin[i]]?nway[v-coin[i]]:1);//nway[v]是指在i-1時的方案數量,表示完全沒有coin[i]的方案數量;而在v之前的下標均表示在i時的方案數量,也就是說至少有一個coin[i]的方案的數量,但是如果nway[v-coin[i]]=0,此時就要加1}}cout<<nway[N]<<endl;

上面的算法有瑕疵,就是如果輸入43

,按照題目的意思應該得0,但是上面的程序會輸出一個40的所有組合

int nway[N+1];memset(nway,0,sizeof(nway));int coin[]= {5,10,20};nway[0] = 1;for (int i=0;i<K;++i){for (int v =coin[i];v<=N;++v){nway[v] = nway[v] + nway[v-coin[i]];}}cout<<nway[N]<<endl;再重新解釋下程序,nway[v]是在0到i-1種貨幣下,組合成v面額的數量;那在0到i種貨幣下,組合成面額v的方案的數量為=不含有第i種貨幣的組合方案數量+至少含有一張第i種貨幣的組合方案數量

其中nway[v-coin[i]]
表示0到i種貨幣組成面額為v-coin[i]的方案的數量,可能含有i貨幣也可能不含有,但是我們預留一個coin[i]的位置,也就使得至少有一張i貨幣;
經過多方論證,用一維nway正好,如果用二維的,就回出錯。


在網上看到另外一種算法:

http://www.cnblogs.com/buptLizer/archive/2012/03/31/2427583.html

求用1,2,5這三個數不同個數組合的和為100的組合個數

?假設a*1 + b*2 + c*5 = 100;非常容易看出c的循環次數最小,那么枚舉c開始

c=0, a的取值為100,98,96,94,...,4,2,0

c=1,a的取值為95,93,91,89,...,5,3,1

c=2,a的取值為90,88,86,...,4,2,1

c=3,a的取值為85,83,81,...,5,3,1

.....

c=19,a的取值為5,3,1

c=20,a的取值0

現在看出規律了吧,100以內的偶數+95以內的奇數+90以內的偶數+。。。+5以內的奇數+0以內的偶數

我們可以立即寫好如下程序:

for(int i = 0; i <= 100; i += 5)

{

??? sum += (m>>1) + 1;

}




總結

以上是生活随笔為你收集整理的零钱组合的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。