题意:有一些货币告诉你每种的数量与币值。让你算在m内能组合成的的数值个数。
思路:数据量比较大,用多重背包的做法是会超时的,所以我们需要用二进制优化,记得以前听过这种写法,但是没有写过。今天终于做到这种题了第一次写参考了http://blog.csdn.net/hellobabygogo3/article/details/8013350 主要思路就是用二进制能组成所有v[i]以下的数。
代码如下:
1 /************************************************** 2 * Author : xiaohao Z 3 * Blog : http://www.cnblogs.com/shu-xiaohao/ 4 * Last modified : 2014-04-02 22:58 5 * Filename : hdu_2844.cpp 6 * Description : 7 * ************************************************/ 8 9 #include <iostream> 10 #include <cstdio> 11 #include <cstring> 12 #include <cstdlib> 13 #include <cmath> 14 #include <algorithm> 15 #include <queue> 16 #include <stack> 17 #include <vector> 18 #include <set> 19 #include <map> 20 #define MP(a, b) make_pair(a, b) 21 #define PB(a) push_back(a) 22 23 using namespace std; 24 typedef long long ll; 25 typedef pair<int, int> pii; 26 typedef pair<unsigned int,unsigned int> puu; 27 typedef pair<int, double> pid; 28 typedef pair<ll, int> pli; 29 typedef pair<int, ll> pil; 30 31 const int INF = 0x3f3f3f3f; 32 const double eps = 1E-6; 33 const int LEN = 2001000; 34 int dp[LEN]; 35 int n, m, a[LEN], c[LEN]; 36 37 int main() 38 { 39 // freopen("in.txt", "r", stdin); 40 41 while(cin >> n >> m){ 42 if(!n && !m) break; 43 memset(dp, 0, sizeof dp); 44 for(int i=0; i<n; i++) cin >> a[i]; 45 for(int i=0; i<n; i++) cin >> c[i]; 46 dp[0] = 1; 47 for(int i=0; i<n; i++){ 48 int j, cnt = c[i]; 49 for(j=1; j<=cnt; j<<=1){ 50 for(int k=m; k>=j*a[i]; k--){ 51 if(dp[k - j*a[i]]) dp[k] = 1; 52 } 53 cnt -= j; 54 } 55 if(cnt){ 56 j = cnt; 57 for(int k=m; k>=j*a[i]; k--) if(dp[k-j*a[i]])dp[k] = 1; 58 } 59 } 60 int ans = 0; 61 for(int i=1; i<=m; i++)if(dp[i]) ans ++; 62 cout << ans << endl; 63 } 64 return 0; 65 }