hdu 2844 Coins 多重背包

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2844

 

算是一个小变式

这道题考对背包问题的理解

cost和weight在此题是一致的

这保证对一个地方不会出现重复更新

然后跑一遍多重背包之后

【dp[]中“dp[i] == i”的位置就说明在此处有一个“更新” 即可以让总额恰好为i】

 

 

#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <stack>
#include <set>
#include <queue>
#include <vector>

using namespace std;

typedef long long ll;

const int maxn = 110;
const int maxm = 100010;
const int INF = 100000;

int a[maxn], c[maxn];
int dp[maxm];
int V;

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

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

void MultiplePack(int cost, int weight, int amount)
{
    if(cost*amount >= V)
    {
        CompletePack(cost, weight);
        return;
    }
    int k = 1;
    while(k < amount)
    {
        ZeroOnePack(k*cost, k*weight);
        amount = amount - k;
        k *= 2;
    }
    ZeroOnePack(amount*cost, amount*weight);
}

int main()
{
    //freopen("in.txt", "r", stdin);

    int n, m;

    while(scanf("%d%d", &n, &m) == 2 && n != 0 && m != 0)
    {
        memset(dp, 0, sizeof(dp));

        for(int i = 0; i < n; i++)
            scanf("%d", &a[i]);

        for(int i = 0; i < n; i++)
            scanf("%d", &c[i]);

        V = m;
        for(int i = 0; i < n; i++)
        {
            MultiplePack(a[i], a[i], c[i]);
        }

        int ans = 0;
        for(int i = 1; i <= m; i++)
        {
            if(dp[i] == i)
                ans++;
        }

        printf("%d\n", ans);
    }


    return 0;
}

 

posted @ 2015-02-19 12:41  地鼠地鼠  阅读(143)  评论(0编辑  收藏  举报