題目描述
母牛們不但建立了它們自己的政府而且選擇了建立了自己的貨幣系統。由於它們特殊的思考方式,它們對貨幣的數值感到好奇。
傳統地,一個貨幣系統是由1,5,10,20 或 25,50, 和 100的單位面值組成的。
母牛想知道有多少種不同的方法來用貨幣系統中的貨幣來構造一個確定的數值。
舉例來說, 使用一個貨幣系統 {1,2,5,10,...}產生 18單位面值的一些可能的方法是:18x1, 9x2, 8x2+2x1, 3x5+2+1,等等其它。 寫一個程式來計算有多少種方法用給定的貨幣系統來構造一定數量的面值。保證總數將會適合long long (C/C++) 和 Int64 (Free Pascal),即在0 到2^63-1之間。
輸入輸出格式
輸入格式:
貨幣系統中貨幣的種類數目是 V (1<=V<=25)。要構造的數量錢是 N (1<= N<=10,000)。
第一行: 二個整數,V 和 N 。
第二行: 可用的貨幣的面值 。
輸出格式:
輸出格式:
單獨的一行包含那個可能的用這v種硬幣湊足n單位貨幣的方案數。
輸入輸出樣例
輸入樣例#1:
3 10 1 2 5
輸出樣例#1:
10
說明
翻譯來自NOCOW
USACO 2.3
這是一個裸完全揹包問題,
雖然題解裡寫的都是一維的,但完全揹包其實可以用二維去寫。。
動態轉移方程:
dp[i][j]=dp[i-1][j]+dp[i][j-a[i]];(j>=a[i])
dp[i][j]=dp[i-1][j];(j<a[i])
初始化:
dp[i][0]=1
但是二維的不論是在空間還是在程式碼複雜度上都劣於一維,但略微易懂。
注意開long long !!!!!!!!!!!!!!!!!
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #define lli long long int 7 using namespace std; 8 const lli MAXN=10001; 9 void read(lli &n) 10 { 11 char c='+';lli x=0;bool flag=0; 12 while(c<'0'||c>'9') 13 {c=getchar();if(c=='-')flag=1;} 14 while(c>='0'&&c<='9') 15 {x=x*10+(c-48);c=getchar();} 16 flag==1?n=-x:n=x; 17 } 18 lli dp[31][10001]; 19 lli v,n; 20 lli a[30]; 21 int main() 22 { 23 read(v);// 擁有的種類 24 read(n);// 需要構造的錢 25 for(lli i=1;i<=v;i++) 26 { 27 read(a[i]); 28 //dp[i][a[i]]=1; 29 dp[i][0]=1; 30 } 31 for(lli i=1;i<=v;i++) 32 for(lli j=1;j<=n;j++) 33 if(j>=a[i]) 34 dp[i][j]=dp[i-1][j]+dp[i][j-a[i]]; 35 else 36 dp[i][j]=dp[i-1][j]; 37 printf("%lld",dp[v][n]); 38 return 0; 39 }