1. 程式人生 > >Piggy-Bank HDU - 1114(題解)

Piggy-Bank HDU - 1114(題解)

sta mil mage rar 不能 possible 多少 microsoft 技術分享

原題

技術分享圖片技術分享圖片

http://acm.hdu.edu.cn/showproblem.php?pid=1114

題目大意

題目是講有一個儲錢罐,給出空罐時重量E,目前罐的重量F,已知罐裏硬幣的種類,有n種,每一種都給出其價值p[i]和重量w[i],問該罐裏至少有多少錢?如果硬幣不能剛好湊夠該重量則輸出-1.

題目解析

為了講題方便,我把題目空罐時質量換成m0,目前罐的重量換成m,價值改成v[i].這道題可以轉換為一個等效的問題,就是給定硬幣種類,每種硬幣有無限個,問能否從這些硬幣中剛好湊成重量為m-m0的硬幣堆,如果能湊的話價值之和要盡可能小.稍微思考後會發現這就是完全背包問題,只是稍微變動而已.首先設一個dp數組,dp[i]表示i重量時硬幣價值之和的最小值.(初始化為INF),dp[0]=0,dp[i]=INF表示這些硬幣不能湊到剛好i重量,然後一遍外循環用i=1→n遍歷所有物品,內循環從j=w[i]→(m-m0)(內循環這樣更新能體現出一種硬幣有無限個的特點)if(dp[j-w[i]]!=INF) dp[j]=min(dp[j],dp[j-w[i]]+v[i])來不斷更新dp數組,最後如果dp[m-m0]不是INF,輸出dp[m-m0],否則輸出-1即可.(j之所以從w[i]開始是為了防止j-w[i]越界,對這個dp還是不太清楚的話可以在草稿紙模擬這個dp數組的更新過程)

代碼

 1 #include <cstdio>
 2 #include <cmath>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <vector>
 7 #include <string>
 8 #include <utility>
 9 #include <queue>
10 #include <stack>
11 const
int INF=0x3f3f3f3f; 12 using namespace std; 13 14 int dp[10001]; 15 int w[501],v[501]; 16 17 int main() 18 { 19 int t; 20 cin>>t; 21 while(t--) 22 { 23 memset(dp,INF,sizeof(dp)); 24 memset(w,0,sizeof(w)); 25 memset(v,0,sizeof(v)); 26 int
m0,m,n; 27 cin>>m0>>m>>n; 28 m-=m0; 29 for(int i=1;i<=n;i++) 30 cin>>v[i]>>w[i]; 31 dp[0]=0; 32 for(int i=1;i<=n;i++) 33 for(int j=w[i];j<=m;j++) 34 if(dp[j-w[i]]!=INF) dp[j]=min(dp[j],dp[j-w[i]]+v[i]); 35 if(dp[m]!=INF) cout<<"The minimum amount of money in the piggy-bank is "<<dp[m]<<.<<endl; 36 else cout<<"This is impossible."<<endl; 37 } 38 return 0; 39 }

Piggy-Bank HDU - 1114(題解)