多重背包

给出N种钱币的面值和每种钱币的个数,问要凑出M的钱最少要用多少枚钱币?

例如:N=4,M=40,钱币面值分别为:3,6,8,9 , 个数分别是:10,10,2,1。

答案为:6。

输入格式

  第一行:2个整数N和M,N范围在[1,50],M范围在[1,1000000]。

第二行:N个整数表示每种钱币的面值,每个数范围在[1,100]。

第三行:N个整数表示每种钱币的数量,每个数范围在[1,100000]。

输出格式

  输出最少钱币数。  输出最少钱币数。如果没有方案,输出-1。

输入/输出例子1

输入:

  2 100

  5 8

  20 6

输出:

  17

样例解释

代码:

#include
using namespace std;
int N,M,d[510],c[510],ans = 0;
int nn,dd[10000],cc[10000];
int f[10000006];
int main(){
    cin>>N>>M;
    for(int i = 1;i <= N;i++){
        cin>>d[i];
    }
    for(int i = 1;i <= N;i++){
        cin>>c[i];
        if(c[i]>M/d[i]){
            c[i] = M/d[i];
        }
    }
    nn = 0;
    for(int i = 1;i <= N;i++){
        int x = c[i];
        for(int p2 = 1;x > p2;p2*=2){
            dd[++nn] = p2*d[i];
            cc[nn] = p2;
            x -= p2;
        }
        if(x > 0){
            dd[++nn] = x*d[i];
            cc[nn] = x;
        }
    }
    f[0] = 1;
    for(int i = 1;i <= nn;i++){
        for(int j = M-dd[i];j >= 0;j--){
            if(f[j]>0){
                if(f[j+dd[i]] == 0|| f[j+dd[i]]>f[j]+cc[i]){
                    f[j+dd[i]] = f[j]+cc[i];
                }
            }
        }
    }
    ans = f[M]-1;
    cout<

你可能感兴趣的:(算法,数据结构,c++,动态规划)