交大OJ 1069 二哥的硬币(多重背包/单调队列)
2017-11-25 20:41
435 查看
二哥的硬币
Description
快放假了,二哥想给女朋友买一个礼物。
走到商店前,发现钱包里只有硬币了。二哥数了一下,一共有n种硬币,面值分别为A1, A2, …, An,每种硬币的个数分别为C1, C2, …, Cn。
二哥心里没有底,他估计要买的礼物价格不会超过m,但不知道到底要买多少钱的礼物。
二哥的硬币已经很多了,他不想再要更多的硬币了,所以他想知道,用手头这些硬币,可以正好凑出1到m中多少种金额(正好相等,包括1和m)。
Input Format
输入包含多组测试数据。
每组测试数据的第一行是空格分隔的两个整数n和m,
1≤n≤100,1≤m≤100000
1≤n≤100,1≤m≤100000
。
接下来有2n个整数,分别是面值A1, A2, …, An,以及硬币个数C1, C2, …, Cn,用空白分隔,
1≤Ai≤100000,1≤Ci≤1000
1≤Ai≤100000,1≤Ci≤1000
。
当读入的n=0且m=0时,表示输入结束;这组数据不需要处理。
Output Format
对于每组测试数据,输出用这些硬币可以正好凑出1到m范围内的多少种金额。
说明
http://poj.org/problem?id=1742
Sample Input
2 5
1 4 2 1
3 10
1 2 4 2 1 1
0 0
Sample Output
4
8
代码如下:
多重背包+单调序列:
dpall[i]:记录面值为i的硬币组合是否存在,相当于查找功能,可减少查找算法的时间
alldatas[]:范围用sets存储,alldata[0]=0,面值组合从alldata[1]开始存储,只记录
<=m的面值数额;
sets:存储<=m的面值数值,sets也是alldata中记录的有效长度。
Description
快放假了,二哥想给女朋友买一个礼物。
走到商店前,发现钱包里只有硬币了。二哥数了一下,一共有n种硬币,面值分别为A1, A2, …, An,每种硬币的个数分别为C1, C2, …, Cn。
二哥心里没有底,他估计要买的礼物价格不会超过m,但不知道到底要买多少钱的礼物。
二哥的硬币已经很多了,他不想再要更多的硬币了,所以他想知道,用手头这些硬币,可以正好凑出1到m中多少种金额(正好相等,包括1和m)。
Input Format
输入包含多组测试数据。
每组测试数据的第一行是空格分隔的两个整数n和m,
1≤n≤100,1≤m≤100000
1≤n≤100,1≤m≤100000
。
接下来有2n个整数,分别是面值A1, A2, …, An,以及硬币个数C1, C2, …, Cn,用空白分隔,
1≤Ai≤100000,1≤Ci≤1000
1≤Ai≤100000,1≤Ci≤1000
。
当读入的n=0且m=0时,表示输入结束;这组数据不需要处理。
Output Format
对于每组测试数据,输出用这些硬币可以正好凑出1到m范围内的多少种金额。
说明
http://poj.org/problem?id=1742
Sample Input
2 5
1 4 2 1
3 10
1 2 4 2 1 1
0 0
Sample Output
4
8
代码如下:
#include <iostream> #include <cstdio> using namespace std; const long long M = 100001;//m<=100000 bool dpall[M];//A[i]:the combination of coins valuing i exists. long long A[101]; long long C[101]; long long alldata[M]; int coins = 0; long long sets = 0; long long m; void setdpallahead(){ for (int i = 0; i < M; i++) { dpall[i] = false; alldata[i] = 0; } } void setdp(){ sets = 0; setdpallahead(); for (int i = 1; i <= coins; i++) {//start from 1. if (i==1) { for(int j=1; j<=C[1]&&j*A[1]<=m; j++){ dpall[j*A[1]] = true; alldata[++sets] = j*A[i]; } }//deal with the condition that j==1. else{//deal with the condition that j>1. long long prevsets = sets;//present scale for (int j = 0; j <= prevsets ; j++) { for (int k = 1; k<=C[i]; k++) { if (alldata[j]+k*A[i]>m) {//alldata[0]==0,so you can take 0+k*A[i] into thought break;//finish the preceding "for" recycle. } if (!dpall[alldata[j]+k*A[i]]) {//this step records that the value alldata[j]+k*A[i]] exists. dpall[alldata[j]+k*A[i]] = true; alldata[++sets] = alldata[j]+k*A[i]; } } } } } } int main(){ scanf("%d%lld", &coins, &m); while (coins!=0||m!=0) { for (int i = 1; i <= coins; i++) { scanf("%lld", &A[i]); } for (int i = 1; i <= coins; i++) { scanf("%lld", &C[i]); } setdp(); printf("%lld\n", sets); scanf("%d%lld", &coins, &m); } return 0; }
多重背包+单调序列:
dpall[i]:记录面值为i的硬币组合是否存在,相当于查找功能,可减少查找算法的时间
alldatas[]:范围用sets存储,alldata[0]=0,面值组合从alldata[1]开始存储,只记录
<=m的面值数额;
sets:存储<=m的面值数值,sets也是alldata中记录的有效长度。
相关文章推荐
- 【算法学习笔记】53.单调队列的简单应用 SJTU OJ 1034 二哥的金链
- POJ 1742 Coins( 单调队列优化多重背包)
- 多重背包模板--二进制优化模板&&单调队列优化模板
- HDOJ 2191 (多重背包/二进制分解/单调队列优化DP)
- 多重背包O(N*V)算法详解(使用单调队列)
- [caioj]单调队列3 单调队列
- 【OJ4976】硬币,神奇的背包
- POJ 1742 Coins(多重背包, 单调队列)
- POJ 1276 Cash Machine (多重背包&单调队列)
- 哈理工oj(acm.hrbust.edu.cn) 1522【单调队列】
- 多重背包O(VN)算法——单调队列优化
- POJ 1742 Coins 多重背包单调队列优化
- poj 1742 多重背包(单调队列)
- POJ - 1742 Coins 多重背包+(二进制优化||单调队列优化)
- 多重背包O(N*V)算法详解(使用单调队列)
- 【多重背包】二进制优化 && 单调队列优化 && w == v 的特殊情况的处理
- 【DP】【单调队列--多重背包】
- 交大OJ 1272 写数游戏/背包问题
- hrbust 哈理工oj 1993数硬币【dp】【背包】
- [BZOJ4182]Shopping 点分治+dfs序+多重背包单调队列