uva 1276 多重背包

二进制拆分  

方法是:将第 i 种物品分成若干件 01 背包中的物品,其中每件物品有一个系
数。这件物品的费用和价值均是原来的费用和价值乘以这个系数。令这些系数分别为
1; 2; 22 : : : 2k-1; Mi - 2k + 1,且 k 是满足 Mi - 2k + 1 > 0 的最大整数。例如,如果 Mi
13,则相应的 k = 3,这种最多取 13 件的物品应被分成系数分别为 1; 2; 4; 6 的四件
物品。
分成的这几件物品的系数和为
Mi,表明不可能取多于 Mi 件的第 i 种物品。另外
这种方法也能保证对于
0 : : : Mi 间的每一个整数,均可以用若干个系数的和表示。这里
算法正确性的证明可以分
0 : : : 2k-1 2k : : : Mi 两段来分别讨论得出,希望读者自己思
考尝试一下。


将cash作为背包的容量,那么硬币所占背包的体积便是数量*面额,价值也是数量*面额

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
#include <map>
using namespace std;
const int INF=1e9+100;

int w[1005],c[1005];
int d[100005];
int main(){
    //freopen("out.txt","w",stdout);
    int n,k1;
    while(scanf("%d",&n)!=EOF){
        scanf("%d",&k1);
        int sum=0;
        for(int i=0;i<k1;i++){
            scanf("%d %d",&w[i],&c[i]);
        }
        memset(d,0,sizeof(d));
        for(int i=0;i<k1;i++){
            int m=w[i],k=1;
            while(k<m){
                for(int j=n;j>=k*c[i];j--){
                    d[j]=max(d[j],d[j-k*c[i]]+k*c[i]);
                }
                m-=k;
                k*=2; 
            }
            for(int j=n;j>=m*c[i];j--){
                d[j]=max(d[j],d[j-m*c[i]]+m*c[i]);
            }
        }
        printf("%d\n",d[n]);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值