最少硬幣問題(動態規劃遞推式)
阿新 • • 發佈:2018-12-16
最少硬幣問題
時間限制(普通/Java) : 1000 MS/ 3000 MS 執行記憶體限制 : 65536 KByte
總提交 : 247 測試通過 : 73
比賽描述
設有n種不同面值的硬幣,各硬幣的面值存於陣列T[1:n]中。現要用這些面值的硬幣來找錢。可以使用的各種面值的硬幣個數存於陣列Coins[1:n]中。對任意錢數0≤m≤20001,設計一個用最少硬幣找錢m的方法。
對於給定的1≤n≤10,硬幣面值陣列T和可以使用的各種面值的硬幣個數陣列Coins,以及錢數m,0≤m≤20001,程式設計計算找錢m的最少硬幣數。
輸入
輸入的第一行中只有1個整數給出n的值,第2行起每行2個數,分別是T[j]和Coins[j]。最後1 行是要找的錢數m。
輸出
輸出計算的最少硬幣數,問題無解時輸出-1。
樣例輸入
3
1 3
2 3
5 3
18
樣例輸出
5
題目來源:http://acm.njupt.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1221
劉汝佳把這個題放在DAG模型的裡,那就代表了這是一道DAG模型題?我咋感覺這題和01揹包這麼像呢。只不過這是有限制硬幣的個數,但是01揹包每個物品只有一個。
看了一些大佬的程式碼然後自己也打了很久,老是錯在輸出那裡。。這個輸出方式有點不太懂,為何f[m]>m就是湊不齊?鬱悶。。
#include<cstdio> #include<algorithm> #include<cstdlib> using namespace std; int coin[11],num[11],f[20005]; int main () { int n,m; scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d%d",&coin[i],&num[i]); scanf("%d",&m); for(int i=1;i<=m;i++) f[i]=0x3f3f3f3f; for(int i=0;i<n;i++)//第i種硬幣 for(int j=1;j<=num[i];j++) { for(int k=m;k>=coin[i];k--)//不斷的在更新狀態的最小值 { f[k]=min(f[k],f[k-coin[i]]+1);//加一的目的就是下面哪那個狀態用了一次I型別硬幣,所加該狀態加一 /懂了 //printf("f[%d]:=min(f[%d],f[%d]+1)=%d\n",k,k,k-coin[i],f[k]); } //system("PAUSE"); } printf("%d\n",f[m]<m?f[m]:-1); }
這個輸出方式有點不太懂,為何f[m]>m就是湊不齊?鬱悶。。