HDU 2844 Coins(多重背包)

点我看题目

题意 :Whuacmers有n种硬币,分别是面值为A1,A2,.....,An,每一种面值的硬币的数量分别是C1,C2,......,Cn,Whuacmers想买钱包,但是想给人家刚好的钱,不喜欢再找钱那么麻烦,但是他不知道钱包的具体钱数,只知道不会超过m,所以问你手里的钱能表示多少个不超过m的钱数。

思路 :多重背包。不知道的去搜背包九讲,几乎都一样。

我想说这个小哥儿真逗

 

#include <stdio.h>

#include <string.h>

#include <iostream>

#include <algorithm>



using namespace std ;



int a[110],c[110] ;

int dp[100010] ;

bool vis[100010] ;

int n, m;



void zeroOnepack(int cost,int weight)

{

    for(int i = m ; i >= cost ; i--)

    dp[i] = max(dp[i],dp[i-cost]+weight) ;

}

void completepack(int cost ,int weight)

{

    for(int i = cost ; i <= m ; i++)

    dp[i] = max(dp[i],dp[i-cost]+weight) ;

}

void multiplepack(int cost,int weight,int amount)

{

    if(cost * amount >= m)

    {

        completepack(cost,weight) ;

        return  ;

    }

    else

    {

        int k = 1 ;

        while(k < amount)

        {

            zeroOnepack(k*cost,k*weight) ;

            amount -= k ;

            k = k*2 ;

        }

        zeroOnepack(amount*cost,amount*weight) ;

    }

}



int main()

{

    while(~scanf("%d %d",&n,&m))

    {

        if(n == 0 && m==0) break ;

        for(int i = 0 ; i < n ; i++)

        scanf("%d",&a[i]) ;

        for(int j = 0 ; j < n ; j++)

        scanf("%d",&c[j]) ;

        memset(dp,0,sizeof(dp)) ;

        int cnt = 0 ;

        for(int i = 0 ; i < n ; i++)

        {

            multiplepack(a[i],a[i],c[i]) ;

        }

        for(int i = 1 ; i <= m ; i++)

        if(dp[i] == i)cnt++ ;

        printf("%d\n",cnt) ;

    }

    return 0 ;

}
View Code

 

你可能感兴趣的:(HDU)