問題描述:現有面值為3,4,5的三種硬幣(每種硬幣可以重複使用),現在去商店買乙個東西要x元,問如何用最少的硬幣付清,而不需要對方找錢,如果無法用手中的硬幣恰好湊出x則列印-1.
樣例:輸入: 1 2 3 6
輸出:-1 -1 1 2
分析:有乙個很直覺的思路就是先盡量用大的硬幣,然後用小的硬幣,舉個栗子:這個題中13元可以分解為先用乙個5元,再用乙個5元,此時發現再用乙個3元硬幣就行了。哦豁,妙哇,完美解決了。
別急,舉個反例看看:27元用2,5,7三種硬幣,你會覺得用3個7再用3個2,一共6個硬幣就行了嗎。其實呢,最少的是1個7和4個5,才5個硬幣。這說明貪心策略只是區域性最優解而不是全域性最優解,而且是暴力,不太具有普遍性。
如果用遞迴法的話,會發現有很多重複計算,而且空間開銷大,也欠妥。
下面列出這道題的動態規劃思路步驟:
1、可以確定a1+a2+a3+...+ak=x元一定成立,且一定有最後的一枚面值為ak的硬幣,而且除掉最後一枚硬幣前面的所有硬幣面值加起來一定是x-ak元
注意:不需要知道前面k-1個硬幣具體是怎麼樣的,甚至不需要知道k和ak,但是可以確定前面的硬幣拼了x-ak元
2、最優子結構:先不看最後乙個ak硬幣,而是要確保前面的x-ak元的拼湊方法一定是用硬幣最少的!!!
設f(x)=湊出x元最少用的硬幣數
這道題不難推出:f(x)=min;
本題的具體資料:
f(0) f(1) f(2) f(3) f(4) f(5) f(6) f(7) f(8) f(9) f(10) f(11)......
需要的硬幣數 0 max max 1 1 1 2 2 . 2 2 2 3 ....
解釋:2=1*2;3=1*3;4=1*4;5=1*5;6=3*2;7=3+4;8=3+5或者4+4(但都是兩枚) ;9=5+4;11=4+4+3(3枚)
初始:b[0]=0,0元不用硬幣
依次算出b[1],b[2],b[3]。。。其中後面的是通過前面的推出來的,不要從大往小推(b[n],b[n-1]...b[2],b[1]),至於為什麼可以仔細想想。
**寫的有點雜。。。主要是確定狀態轉移方程中最優子結構時用了輔助變數fl和min
#include#define max 100000
int b[10000];
int main()
;int n,i,j;
scanf("%d",&n)//輸入總**
b[0]=0;//初始化0元不需要硬幣
for(i=1;i<=n;i++)//每次迴圈確定乙個b[i]的值,b[i]要麼是max(湊不出硬幣),要麼是乙個比較小的數
if(i-a[j]>=0&&fl)
if(b[n]>=max)//這是不能湊出硬幣的情況列印-1表示
printf("-1");
else
printf("%d",b[n]);
}
動態規劃 硬幣問題
這是乙個固定重點的最長路和最短路問題,可用動態規劃問題來求解 代表硬幣總值,n代表硬幣總數,v陣列儲存硬幣各個面值,d代表從i出發到結點0的路徑的最長路徑長度或最短路徑長度 vis代表是否訪問過該結點 int n,s,v maxn d maxn vis maxn int dpmax int s re...
動態規劃 硬幣問題
2013 07 11 03 17 5610人閱讀收藏 舉報 演算法和資料結構學習 79 最少硬幣問題 假設有3種不同的硬幣,幣值分別是coinvalue 每一種硬幣的數量是有限的,分別是coinnum 給定乙個數值target 18,找出一種硬幣數最少的方法,輸出最少的硬幣數。思路 動態規劃。問題定...
動態規劃 硬幣問題
問題描述 輸入總金額n,硬幣不同價值的種類m,m種硬幣的面值 例如 15 6 1 2 7 8 12 50 輸出湊成n最少的硬幣數 1 貪心演算法 每次都選擇面值最大的。問題在於,求出來的並不是最優解,上例中,用貪心解出來的結果為3 1,2,12 而實際為2 7,8 include includeus...