一本通 提高篇 10179. Banknotes.
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
#include <deque>
using namespace std;
/*
https://loj.ac/p/10179
题目描述
原题来自:POI 2005
Byteotian Bit Bank (BBB) 拥有一套先进的货币系统,这个系统一共有 n 种面值的硬币,
面值分别为 b_1, b_2,~~~ , b_n。但是每种硬币有数量限制,
现在我们想要凑出面值 k,求最少要用多少个硬币。
输入格式
第一行一个数 n;
接下来一行 n 个整数 b_1, b_2,~~~ , b_n;
第三行 n 个整数 c_1,c_2,~~~ ,c_n,表示每种硬币的个数;
最后一行一个数 k,表示要凑的面值数。
输出格式
第一行一个数表示最少需要付的硬币数。
样例
输入
3
2 3 5
2 2 1
13
输出
3
数据范围与提示
对于全部数据,1<= n<= 200,1<= b_1<= b_2<= ~~ <= b_n<= 2 * 10^4,1<= c_i,k<= 2 * 10^4。
3
300 700 4800
10000 10000 10000
5000
3
3 7 48
100 100 100
50
*/
const int N = 20010;
int b[N], c[N];
int dp[205][N];
int n;
int k;
//多重背包 单调队列优化 todo
int main()
{
memset(dp, 0x3f, sizeof dp);
dp[0][0] = 0;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> b[i];
}
for (int i = 1; i <= n; i++) {
cin >> c[i];
}
cin >> k;
for (int i = 1; i <= n; i++) {
int dd = 0;
for (int j = 0; j < b[i]; j++) {
deque<int> q;
dp[i][j] = dp[i - 1][j];
for (int p = j; p <= k; p += b[i]) {
while (!q.empty() && p-b[i]*c[i] > q.front()) q.pop_front();
while (!q.empty() && dp[i - 1][q.back()] + (p-q.back())/b[i] >= dp[i - 1][p]) q.pop_back();
q.push_back(p);
dp[i][p] = min(dp[i][p], dp[i - 1][q.front()] + (p - q.front()) / b[i]);
}
}
//cout << dp[i][k] << ". i=" <<i<<",k=" << k << endl;
}
cout << dp[n][k] << endl;
return 0;
}
作 者: itdef
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
![阿里打赏](https://files.cnblogs.com/files/itdef/ali2.bmp)
![微信打赏](https://files.cnblogs.com/files/itdef/weixin2.bmp)