【背包专题】 D - Coins hdu2844【多重背包】

Whuacmers use coins.They have coins of value A1,A2,A3...An Silverland dollar. One day Hibix opened purse 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.

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;
}
				
时间: 2024-10-10 08:59:22

【背包专题】 D - Coins hdu2844【多重背包】的相关文章

HDU 2844 Coins【多重背包】

大意: 有n种物品 告诉你每种物品的价值和数量 问你能拼凑出1--m之内的多少个数 分析: 多重背包 代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 const int maxn = 100005; 7 int dp[maxn]; 8 int num[maxn], va[maxn]; 9 int vo[maxn]; 10 int n

poj 1742 Coins (多重背包)

http://poj.org/problem?id=1742 n个硬币,面值分别是A1...An,对应的数量分别是C1....Cn.用这些硬币组合起来能得到多少种面值不超过m的方案. 多重背包,不过这题很容易超时,用背包九讲的代码有人说行,但是我提交还是超时,后来参考别人代码加了一些优化才能过,有时间要去搞清楚多重背包的单调队列优化. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using

POJ 1742 Coins 【多重背包DP】

题意:有n种面额的硬币.面额.个数分别为A_i.C_i,求最多能搭配出几种不超过m的金额? 思路:dp[j]就是总数为j的价值是否已经有了这种方法,如果现在没有,那么我们就一个个硬币去尝试直到有,这种价值方法有了的话,那么就是总方法数加1.多重背包可行性问题 传统多重背包三重循环会超时,因为只考虑是否可行,没有考虑剩余面额数量的因素. o(n*v)方法 #include <iostream> #include <cstdio> #include <string.h> #

hdu2844 多重背包模板

01 背包 有n 种不同的物品,每个物品有两个属性,size 体积,value 价值,现在给一个容量为 w 的背包,问最多可带走多少价值的物品. int f[w+1]; //f[x] 表示背包容量为x 时的最大价值 for (int i=0; i<n; i++) for (int j=w; j>=size[i]; j--) f[j] = max(f[j], f[j-size[i]]+value[i]); //逆序 完全背包 如果物品不计件数,就是每个物品有无数件的话,稍微改下即可 for (i

poj1742 Coins【多重背包】【贪心】

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

poj1742 Coins(多重背包+单调队列优化)

/* 这题卡常数.... 二进制优化或者单调队列会被卡 必须+上个特判才能过QAQ 单调队列维护之前的钱数有几个能拼出来的 循环的时候以钱数为步长 如果队列超过c[i]就说明队头的不能再用了 拿出来 时刻维护sum表示之前的+v[i]能凑出j来的有几种 注意先进队在更新f */ #include<iostream> #include<cstdio> #include<cstring> #define maxm 100010 #define maxn 110 using

hdu 2844 coins (多重背包)

#include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> using namespace std; int a[120],c[120]; int dp[100000+100]; int main() { int n,m; int i,j,k; while(scanf("%d%d",&n,&m

POJ 3260 The Fewest Coins 最少硬币个数(完全背包+多重背包,混合型)

题意:FJ身上有各种硬币,但是要买m元的东西,想用最少的硬币个数去买,且找回的硬币数量也是最少(老板会按照最少的量自动找钱),即掏出的硬币和收到的硬币个数最少. 思路:老板会自动找钱,且按最少的找,硬币数量也不限,那么可以用完全背包得出组成每个数目的硬币最少数量.而FJ带的钱是有限的,那么必须用多重背包,因为掏出的钱必须大于m,那么我们所要的是大于等于m钱的硬币个数,但是FJ带的钱可能很多,超过m的很多倍都可能,那么肯定要有个背包容量上限,网上说的根据抽屉原理是m+max*max,这里的max指

POJ1742 Coins 多重背包+贪心

Vjudge传送门 $Sol$ 首先发现这是一个多重背包,所以可以用多重背包的一般解法(直接拆分法,二进制拆分法...) 但事实是会TLE,只能另寻出路 本题仅关注“可行性”(面值能否拼成)而不是“最优性”,这是一个特殊之处. 从这里找优化 在“最优性”的问题中,$f[j]$从$f[j]$或$f[j-a[i]]$中转移而来:而在这样的“可行性”问题中,其实只要$f[j]$可行,我们就可以不用考虑$f[j-a[i]$了,也可以反过来说. 于是我们可以考虑一种贪心策略,设$used[j]$表示$f[

(多重背包+记录路径)Charlie&#39;s Change (poj 1787)

http://poj.org/problem?id=1787 描述 Charlie is a driver of Advanced Cargo Movement, Ltd. Charlie drives a lot and so he often buys coffee at coffee vending machines at motorests. Charlie hates change. That is basically the setup of your next task. Your