博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
poj1742 Coins【多重背包】【贪心】
阅读量:5356 次
发布时间:2019-06-15

本文共 2715 字,大约阅读时间需要 9 分钟。

Coins
Time Limit: 3000MS   Memory Limit: 30000K
Total Submissions:43969   Accepted: 14873

Description

People in Silverland use coins.They have coins of value A1,A2,A3...An Silverland dollar.One day Tony opened his money-box and found there were some coins.He decided to buy a very nice watch in a nearby shop. He wanted to pay the exact price(without change) and he known the price would not more than m.But he didn't know the exact price of the watch. 
You are to write a program which reads n,m,A1,A2,A3...An and C1,C2,C3...Cn corresponding to the number of Tony's coins of value A1,A2,A3...An then calculate how many prices(form 1 to m) Tony can pay use these coins. 

Input

The input contains several test cases. The first line of each test case contains two integers n(1<=n<=100),m(m<=100000).The second line contains 2n integers, denoting A1,A2,A3...An,C1,C2,C3...Cn (1<=Ai<=100000,1<=Ci<=1000). The last test case is followed by two zeros.

Output

For each test case output the answer on a single line.

Sample Input

3 101 2 4 2 1 12 51 4 2 10 0

Sample Output

84

Source

 

题意:有n种硬币,每一枚有一个价值和个数。现在取出一些硬币,面值相加得到结果S。问1~m之间可以得到多少种结果S

思路:硬币为物品,面值为体积,m为背包总容积。一次考虑每种硬币是否被用于拼成最终的面值,以“已经考虑过的物品种数”i作为DP的阶段。阶段i时,dp[j]表示前i种硬币能否拼成面值j。

但是这道题只关注“可行性”而不是“最优性”,可以发现前i种硬币能够拼成面值j只有两种可能。1、前i-1种就可以拼成面值j 2、使用了第i种硬币,发现dp[j-ai]为true,从而dp[j]变为true

于是就有一种贪心策略:设used[j]表示dp[j]在阶段i时为true至少要用到多少枚第i种硬币,并尽量选择第一种情况。在dp[j-ai]为true时,如果dp[j]已经为true,则不执行dp转移,并令used[j]=0。否则执行dp[j] = dp[j] or dp[j - ai]的转移,并令used[j] = used[j - ai] + 1

 

多重背包问题可以将物品拆分变成01背包问题。拆分方法有直接拆分法,二进制拆分法和单调队列。

二进制拆分法是把数量为Ci的第i种物品拆分成p+2个物品,p是满足2^0 + 2^1 + 2^2 + ... + 2^p <= Ci的最大的整数。

他们的体积分别为2^0*Vi, 2^1*Vi, ..., 2^p*Vi, Ri * Vi, 其中Ri= Ci - 2^0 - 2^1 - 2^2 - ... - 2^p

1 //#include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 9 #define inf 0x3f3f3f3f10 using namespace std;11 typedef long long LL;12 13 int n, m;14 const int maxn = 105;15 const int maxm = 1e5 + 5;16 int a[maxn], c[maxn];17 int used[maxm];18 bool dp[maxm];19 20 int main()21 {22 while(scanf("%d%d", &n, &m) != EOF && (n || m)){23 for(int i = 1; i <= n; i++){24 scanf("%d", &a[i]);25 }26 for(int i = 1; i <= n; i++){27 scanf("%d", &c[i]);28 }29 30 memset(dp, 0, sizeof(dp));31 dp[0] = true;32 for(int i = 1; i <= n; i++){33 memset(used, 0, sizeof(used));34 for(int j = a[i]; j <= m; j++){35 if(!dp[j] && dp[j - a[i]] && used[j - a[i]] < c[i]){36 dp[j] = true;37 used[j] = used[j - a[i]] + 1;38 }39 }40 }41 42 int ans = 0;43 for(int i = 1; i <= m; i++){44 if(dp[i])ans++;45 }46 printf("%d\n", ans);47 }48 return 0;49 }

 

转载于:https://www.cnblogs.com/wyboooo/p/9757029.html

你可能感兴趣的文章
Java中的编码
查看>>
PKUWC2018 5/6
查看>>
As-If-Serial 理解
查看>>
洛谷P1005 矩阵取数游戏
查看>>
在Silverlight中使用HierarchicalDataTemplate为TreeView实现递归树状结构
查看>>
无线通信基础(一):无线网络演进
查看>>
关于python中带下划线的变量和函数 的意义
查看>>
linux清空日志文件内容 (转)
查看>>
Servlet接收JSP参数乱码问题解决办法
查看>>
Ajax : load()
查看>>
MySQL-EXPLAIN执行计划Extra解释
查看>>
Zookeeper概述
查看>>
Linux自己安装redis扩展
查看>>
luoguP3414 SAC#1 - 组合数
查看>>
图片点击轮播(三)-----2017-04-05
查看>>
直播技术细节3
查看>>
《分布式服务架构:原理、设计于实战》总结
查看>>
java中new一个对象和对象=null有什么区别
查看>>
字母和数字键的键码值(keyCode)
查看>>
IE8调用window.open导出EXCEL文件题目
查看>>