标签:思路 space can ... def put integer acm scan
InputThe 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.OutputFor each test case output the answer on a single line.Sample Input
3 10 1 2 4 2 1 1 2 5 1 4 2 1 0 0
Sample Output
8 4
题意:问能够将输入的钱币组合为1~m之间的数的种类总数,比如样例2:m=5,钱币可以组合为:1,2,4,5.所以总的种类数为4.
思路:在这道题中我们可以把一定数量组合而成的钱币总价值(1~m)看多背包费用和价值,最后判断费用和价值相等即记入总数。
还可以把每种钱币对应的每个数量计算出来,当作01背包来写这道题:http://blog.csdn.net/hello_sheep/article/details/77581462
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define N 100010 int dp[N],value[110],num[110]; int n,m,ans; void CompletePack(int value,int cost) { int i; for(i = cost; i <= m; i ++) dp[i] = max(dp[i],dp[i-cost]+value); return; } void ZeroOnePack(int value,int cost) { int i; for(i = m; i >= cost; i --) dp[i] = max(dp[i],dp[i-cost]+value); return; } void MultiplePack(int num,int value,int cost) { int k; if(value*num > m) CompletePack(value,cost); else { k = 1; while(k < num) { ZeroOnePack(k*value,k*cost); num -= k; k*=2;//为什么用左移运算符就tle!! } if(num) ZeroOnePack(num*value,num*cost); } return; } int main() { int i,j; while(scanf("%d%d",&n,&m),m+n) { memset(dp,0,sizeof(dp)); for(i = 1; i <= n; i ++) scanf("%d",&value[i]); for(i = 1; i <= n; i ++) scanf("%d",&num[i]); for(i = 1; i <= n; i ++) MultiplePack(num[i],value[i],value[i]); ans = 0; for(i = 1; i <= m; i ++) if(dp[i] == i)//费用和价值相等,满足条件 ans++; printf("%d\n",ans); } return 0; }
【背包专题】 D - Coins hdu2844【多重背包】
标签:思路 space can ... def put integer acm scan
原文地址:http://www.cnblogs.com/chengdongni/p/7429656.html