Banknotes
题目描述
Byteotian Bit Bank(BBB)拥有一套先进的货币系统,这个系统一共有n种面值的硬币,面值分别为b_1,b_2, \cdots,b_nb1,b2,⋯,bn。但是每种硬币有数量限制,现在我们想要凑出面值k,求最少要用多少个硬币。
输入描述:
第一行一个数n;
接下来一行n个整数b_1,b_2, \cdots,b_nb1,b2,⋯,bn;
第三行n个整数c_1,c_2, \cdots,c_nc1,c2,⋯,cn,表示每种硬币的个数;
最后一行一个数k,表示要凑的面值数。
输出描述:
第一行一个数表示最少需要付的硬币数。
输入
3 2 3 5 2 2 1 10
输出
3
备注:
对于全部数据,1 \leq n \leq 200,1 \leq b_1 \lt b_2 \lt \cdots \lt b_n \leq 2 \times10^4,1 \leq c_i,k \leq 2 \times10^41≤n≤200,1≤b1<b2<⋯<bn≤2×104,1≤ci,k≤2×104。
//x1 * b1 + x2 * b2 + x3 * b3 + ... + xn * bn = k //单调队列优化背包dp模板题 #include<bits/stdc++.h> using namespace std; const int N = 1e6 + 7; int b[N], c[N], dp[N], q[N], n; int calc(int i, int u, int k) { return dp[u + k * b[i]] - k; } int main() { int k; cin >> n; memset(dp, 0x3f, sizeof(dp)); for (int i = 1; i <= n; i++) cin >> b[i]; for (int i = 1; i <= n; i++) cin >> c[i]; cin >> k; dp[0] = 0; for (int i = 1; i <= n; i++) { for (int u = 0; u < b[i]; u++) { int l = 1, r = 0; int maxp = (k - u) / b[i]; for (int k = maxp - 1; k >= max(maxp - c[i], 0); k--) { while (l <= r && calc(i, u, q[r]) >= calc(i, u, k)) r--; q[++r] = k; } for (int p = maxp; p >= 0; p--) { while (l <= r && q[l] > p - 1) l++; if (l <= r) dp[u + p * b[i]] = min(dp[u + p * b[i]], calc(i, u, q[l]) + p); if (p - c[i] - 1 >= 0) { while (l <= r && calc(i, u, q[r]) >= calc(i, u, p - c[i] - 1)) r--; q[++r] = p - c[i] - 1; } } } } cout << dp[k] << endl; return 0; }