hdu 2844 Coins(DP, 背包)
2014-11-30 17:44
417 查看
题意:硬币的面值 A1....An, 每种面值持有数 C1....Cn, 求 [1, m] 中能够凑出的面值数。
多重背包附加二进制优化buff。。。
Ai * Ci >= m 的情况用完全背包处理。。。
挺好的一道题,两种背包都考了还加个优化。。。
------------------------------------------------------------------------------
又写了一遍,发现 Ai*Ci>=m 时,不搞完全背包也能过。。。
多重背包附加二进制优化buff。。。
Ai * Ci >= m 的情况用完全背包处理。。。
挺好的一道题,两种背包都考了还加个优化。。。
#include<iostream> #include<cstdio> #include<cstdlib> #include<map> #include<algorithm> #include<vector> #include<queue> #include<cstring> #include<set> #include<list> #include<cmath> using namespace std; typedef long long LL; const int maxn = 100; const int inf = 0x7fffffff; int a[maxn+5]; int c[maxn+5]; int f[100000+5]; vector<int> pack[maxn+5]; int n, m; void do_pack(int idx) { pack[idx].clear(); int num = c[idx]; if (num * a[idx] >= m) return; int base = 1; vector<int> tmp; while (num >= base) { tmp.push_back(base); num -= base; base <<= 1; } if (num) tmp.push_back(num); int sz = tmp.size(); for (int i=sz-1;i>=0;--i) pack[idx].push_back(tmp[i]); } void print(int * A, int n) { for (int i=0;i<=n;++i) cout << A[i] << " ";cout << endl; } int main() { //freopen("input.in", "r", stdin); while (scanf("%d%d",&n,&m)) { if (n == 0 && m == 0) break; for (int i=1;i<=n;++i) scanf("%d",&a[i]); for (int i=1;i<=n;++i) scanf("%d",&c[i]); for (int i=1;i<=n;++i) do_pack(i); //print(a, n); //print(c, n); #if 0 for (int i=1;i<=n;++i) { cout << "pack " << i << ": "; int sz = pack[i].size(); for (int j=0;j<sz;++j) cout << pack[i][j] << " ";cout << endl; } #endif for (int i=0;i<=m;++i) f[i] = 0; f[0] = 1; for (int i=1;i<=n;++i) { //cout << "fuck " << i << " size: " << pack[i][0] << endl; if (c[i]*a[i] >= m) { for (int j=a[i];j<=m;++j) f[j] |= f[j-a[i]]; continue; } int sz = pack[i].size(); for (int k=0;k<sz;++k) for (int j=m;j>=0;--j) { if (f[j]) continue; if (j-a[i]*pack[i][k] >= 0) { //cout << "fuck k " << k << endl; f[j] |= f[j-a[i]*pack[i][k]]; } #if 0 print(f, m); #endif } } int ans = 0; for (int i=1;i<=m;++i) if (f[i]) ++ans; printf("%d\n", ans); } return 0; }
------------------------------------------------------------------------------
又写了一遍,发现 Ai*Ci>=m 时,不搞完全背包也能过。。。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <vector> #include <queue> #include <stack> #include <cassert> #include <algorithm> #include <cmath> #include <limits> #include <set> #include <map> using namespace std; #define SPEED_UP iostream::sync_with_stdio(false); #define FIXED_FLOAT cout.setf(ios::fixed, ios::floatfield); #define rep(i, s, t) for(int (i)=(s);(i)<=(t);++(i)) #define urep(i, s, t) for(int (i)=(s);(i)>=(t);--(i)) typedef long long LL; const int Maxn = 100000; struct Node{ int v, t; }; int n, m, v[100+5], t[100+5], f[Maxn+5]; vector<Node> vec; bool init() { cin >> n >> m; if (!n && !m) return false; rep(i, 0, n-1) cin >> v[i]; rep(i, 0, n-1) cin >> t[i]; vec.clear(); rep(i, 0, n-1) { int sz = 1, left = t[i]; while (left >= sz) { vec.push_back((Node){v[i], sz}); left -= sz; sz <<= 1; } if (left) vec.push_back((Node){v[i], left}); } return true; } int main() { #ifndef ONLINE_JUDGE freopen("input.in", "r", stdin); #endif SPEED_UP while (init()) { int sz = vec.size(); memset(f, 0, sizeof(f)); f[0] = 1; rep(i, 0, sz-1) { int _v = vec[i].v * vec[i].t; urep(j, m, _v) f[j] |= f[j-_v]; } int cnt = 0; rep(i, 1, m) cnt += f[i]; cout << cnt << endl; } return 0; }
相关文章推荐
- HDU - 2844 - Coins (多重背包,dp)
- HDU 2844 Coins (多重背包问题DP)
- hdu 2844 Coins(dp 多重背包)
- hdu 2844 coins DP多重背包
- DP(分组背包两种二进制优化) Problem S:Coins(HDU 2844)
- HDOJ(HDU).2844 Coins (DP 多重背包+二进制优化)
- hdu 2844 Coins(dp 多重背包 二进制优化)
- HDU 2844 Coins(DP 背包)
- Coins - HDU 2844 背包dp
- hdu 2844 Coins(多重背包+二进制优化)
- hdu 2844 Coins 多重背包 二进制优化 算是否能组成的背包
- HDU 2844 Coins (多重背包+二进制优化模板)
- HDU-2844 Coins 多重背包
- HDU 2844 Coins(多重背包)
- hdu 2844 Coins(多重背包+二进制优化)
- hdu 2844 Coins(多重背包 可达不可达)
- hdu 2844 Coins 背包
- hdu 2844 Coins(多重背包优化)
- Coins(HDU 2844):一个会超时的多重背包
- HDU 2844 Coins(多重背包+二进制优化)