HDU2844-Coins(多重揹包 二進制優化 模板)

題目鏈接

Problem Description

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.

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 10

1 2 4 2 1 1

2 5

1 4 2 1

0 0

Sample Output

8

4


題意

多重揹包,每個物品給了固定的數量。

思路

多重揹包可以看做是01揹包+完全揹包

01揹包 和 完全揹包的比較

01揹包逆序,完全揹包順序。

對於多重揹包,如果物品數量足夠多,多到你用不完,就已經裝滿了,其實可以看成是完全揹包。如果有幾個相同的物品,可以看成是幾個獨立的,轉化爲01揹包。

關於01揹包的二進制優化,比如有17個相同的物品,可以看成1,2,4,8,2的01揹包。因爲1,2,4,8,2這五個數可以組成任意的1-17的數,如果看成17個獨立的物品,1,1,...,1,1,會很費時間。


#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define ll long long
#define inf 0x3f3f3f3f

using namespace std;
const int N = 200010;

int dp[N];
int c[N],w[N],num[N];
int n,m;

void ZeroOne_Pack(int cost,int weight,int n)
{
    for(int i=n; i>=cost; i--)
        dp[i] = max(dp[i],dp[i-cost] + weight);
}

void Complete_Pack(int cost,int weight,int n)
{
    for(int i=cost; i<=n; i++)
        dp[i] = max(dp[i],dp[i-cost] + weight);
}

int Multi_Pack(int c[],int w[],int num[],int n,int m)
{
    memset(dp,0,sizeof(dp));
    for(int i=1; i<=n; i++)
    {
        if(num[i]*c[i] > m)
            Complete_Pack(c[i],w[i],m);
        else{
            int k = 1;
            while(k < num[i]){
                ZeroOne_Pack(k*c[i],k*w[i],m);
                num[i] -= k;
                k <<= 1;
            }
            ZeroOne_Pack(num[i]*c[i],num[i]*w[i],m);
        }
    }
    return dp[m];
}

int main()
{
    while(~scanf("%d%d",&n,&m),n+m)
    {
        for(int i=1;i<=n; i++) cin>>w[i];
        for(int i=1;i<=n; i++) cin>>num[i];
        Multi_Pack(w,w,num,n,m);
        int ans = 0;
        for(int i=1;i<=m;i++){
            if(dp[i]==i) ans++;
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章