1. 程式人生 > >最少硬幣問題(動態規劃遞推式)

最少硬幣問題(動態規劃遞推式)

最少硬幣問題

時間限制(普通/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就是湊不齊?鬱悶。。