HDU 2844 Coins 多重背包

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=2844

Coins

Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
#### 问题描述 > 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.

输入

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.

输出

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

样例输入

3 10
1 2 4 2 1 1
2 5
1 4 2 1
0 0

样例输出

8
4

题解

裸的多重背包,这里提供两种思路:
1、开个cntv数组维护一下第i个背包用了几次,限制一些非法的转移,像完全背包那一做一遍就ok。

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#include<sstream>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define scf scanf
#define prf printf

typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII;

const int INF=0x3f3f3f3f;
const LL INFL=0x3f3f3f3f3f3f3f3fLL;
const double eps=1e-8;
const double PI = acos(-1.0);

//start----------------------------------------------------------------------

const int maxn=101010;

int cntv[maxn];
bool dp[maxn];
int v[maxn],c[maxn];

int main() {
    int n,m;
    while(scf("%d%d",&n,&m)==2&&n){
        clr(dp,0);
        for(int i=1;i<=n;i++) scf("%d",&v[i]);
        for(int i=1;i<=n;i++) scf("%d",&c[i]);

        clr(dp,0);
        dp[0]=1;

        for(int i=1;i<=n;i++){
            clr(cntv,0);
            for(int j=v[i];j<=m;j++){
                if(!dp[j]&&dp[j-v[i]]&&cntv[j-v[i]]<c[i]){
                    dp[j]=1;
                    cntv[j]=cntv[j-v[i]]+1;
                }
            }
        }

        int ans=0;
        for(int i=1;i<=m;i++) ans+=dp[i];

        prf("%d
",ans);
    }

    return 0;
}

//end-----------------------------------------------------------------------

2、用二进制拆分转化成01背包。

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#include<sstream>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define scf scanf
#define prf printf

typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII;

const int INF=0x3f3f3f3f;
const LL INFL=0x3f3f3f3f3f3f3f3fLL;
const double eps=1e-8;
const double PI = acos(-1.0);

//start----------------------------------------------------------------------

const int maxn=101010;

int cntv[maxn];
bool dp[maxn];
int v[maxn],c[maxn];

int main() {
    int n,m;
    while(scf("%d%d",&n,&m)==2&&n){
        clr(dp,0);
        for(int i=1;i<=n;i++) scf("%d",&v[i]);
        for(int i=1;i<=n;i++) scf("%d",&c[i]);

        VI arr;
        for(int i=1;i<=n;i++){
            int j=1;
            //二进制拆分
            while(c[i]>0){
                if(c[i]>=j){
                    arr.pb(v[i]*j);
                    c[i]-=j;
                }else{
                    arr.pb(v[i]*c[i]);
                    c[i]=0;
                }
                j<<=1;
            }
        }

        clr(dp,0);
        dp[0]=1;

        for(int i=0;i<arr.sz();i++){
            for(int j=m;j>=arr[i];j--){
                dp[j]=dp[j]|dp[j-arr[i]];
            }
        }

        int ans=0;
        for(int i=1;i<=m;i++) ans+=dp[i];

        prf("%d
",ans);
    }

    return 0;
}

//end-----------------------------------------------------------------------
原文地址:https://www.cnblogs.com/fenice/p/5917304.html