給定指定的硬幣種類,面值為 1, 3, 5(在此具體化些),給定所找零的錢數 sum,給出最少的硬幣找零數,每個種類的硬幣無限使用。
看到這問題,當時我想到用貪心演算法來求解,最後求解方案因為巧合對了,後來在網上看到動態規劃的題目,才知道貪心演算法得不到最優解,比如 給定 面值為 1, 3, 4,給定找零數為 6,用貪心法得出方案 [4,1,1],但顯然 [3,3] 方案即可。分析下問題,想一下若存在最少硬幣數 num 滿足當前給定的找零數 sum,則是不是一定存在最少硬幣數 num-1 滿足找零數 sum - (1, 3, 5 )?答案是存在,想一想就知道,當然邊界除外。這個類似於最短路徑的 dijkstra演算法。
對於上面這個思路的實現方案,我用的是回溯思想,擼乙個遞迴函式,不斷遞迴查詢給定硬幣數,給定金額的方案。在此設定乙個標誌位 is_find ,若找到 賦值為 true 。在外面套一層迴圈使得 硬幣數 從 1 不斷增加,若找不到則 硬幣數 + 1 繼續找,若找到 則退出迴圈(通過判斷 is_find ), 找的過程中需要儲存資料,在此宣告乙個陣列變數 coin_kind 儲存方案,每次遞迴將下標為 num 的陣列元素設定為 當前選擇的硬幣值,這是回溯的思想,具體看**。
思想是動態規劃的思想,動態規劃有個動態方程,感覺這個問題動態方程比較簡單,寫出來可能還不如描述下思想,我感覺重點在於怎麼儲存找的方案,在此用的回溯法不斷的重寫固定下標的元素,這一點很重要。另外,該演算法使用遞迴,並且沒有儲存當前狀態,有優化的空間,可以用遞迴法。#include#includeint coin[3] = ; /* 硬幣種類 */
int coin_kind_num = 3; /* 硬幣種類數量 */
int sum = 7; /* 找零錢數 */
int min_coin_num; /* 硬幣最少數 */
int coin_kind[1000]; /* 存放最少數的方案 */
bool is_find = false; /* 是否找到硬幣 */
/* 函式:列印方案
列印存放找零方案的 陣列coin_kind
*/ bool output()
printf("\n");
}/* 函式:初始化方案陣列
初始化存放找零方案的數字 ,使元素全部為 0,以便判斷輸出
*/void initcoinkind()
/* 函式:查詢基本函式
該函式用於給定 指定硬幣數 和 指定應找零的錢數,看是否能找開,用的回溯法查詢.
思想是 若存在對於給定應找零的錢數 sum,存在最少硬幣數 num,則對於 sum - coin[i] ( i = 0, ..., coin_kind_num - 1)
仍然存在最少硬幣數 num - 1, 類似於 最短路徑那個 dijkstra演算法 。
@param num 指定硬幣數
@param sum 指定應找零的錢數
*/bool findcoin(int num, int sum) else if (sum > 0) else
} else }
} /* 函式:硬幣數逐漸 + 1 查詢
由於查詢方案基本函式只能給定指定硬幣數 num 和指定找零數 sum,
所以 應該使得指定硬幣數從小到大, 從 1 開始,每次查詢完畢判斷 is_find 的值,
若為 false 則 num + 1,繼續查詢
否則 退出迴圈查詢完畢。
*/ bool startfind()
}int main()
硬幣找零問題 動態規劃問題
看到了 這文章,由於我不太懂他的 所以我按他的題和思路,寫了 思路我就不寫了,就是動態規劃的思路,先保證區域性最優,再慢慢向全區域性最優 include include include include using namespace std const int m 100 int coinsum m...
動態規劃 硬幣找零
時間限制 1000 ms 記憶體限制 65535 kb 描述在現實生活中,我們經常遇到硬幣找零的問題,例如,在發工資時,財務人員就需要計算最少的找零硬幣數,以便他們能從銀行拿回最少的硬幣數,並保證能用這些硬幣發工資。我們應該注意到,人民幣的硬幣系統是 100,50,20,10,5,2,1,0.5,0...
動態規劃 最小硬幣找零問題
這題很典型是動態規劃問題,為什麼呢?首先我們可以看一下什麼問題可以被看做動態規劃問題。因此動態規劃的精髓在於,充分利用上一次的計算結果來達成本次快速計算的目的 ok,一般我們解決動態規劃問題可分為三步走 分析問題的狀態時,不要分析整體,只分析最後乙個階段即可!因為動態規劃問題都是劃分為多個階段的,各...