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
",cnt) ;
    }
    return 0 ;
}
View Code
原文地址:https://www.cnblogs.com/luyingfeng/p/3612283.html