poj 1742 多重背包入门

题意:

给n种硬币的价值和数量,求能凑成【 1, m】之间的多少个数。


解析:

完全背包的入门题。

用dp[ i ] = 0 表示 i 这个数不能凑成;

dp[ i ] = 1表示 i 这个数能凑成。

然后每种数量用多重背包的二进制来拆分,最后遍历一遍即可。


代码:

多重背包(01、完全):

int packV;
int n;
int dp[maxv];

// for (int i = 1; i <= n; i++)
//	zeroOnePack(c[i], w[i]);
void zeroOnePack(int cost, int weight)
{
	for (int v = packV; v >= cost; v--)
	{
		dp[v] = max(dp[v], dp[v - cost] + weight);
	}
}
// for (int i = 1; i <= n; i++)
//	completePack(c[i], w[i]);
void completePack(int cost, int weight)
{
	for (int v = cost; v <= packV; v++)
	{
		dp[v] = max(dp[v], dp[v - cost] + weight);
	}
}

void multiplePack(int cost, int weight, int amount)
{
	if (packV <= cost * amount)//相当于无限个物品
	{
		completePack(cost, weight);
	}
	else//01背包来枚举当前物品取几件
	{
		int k = 1;
		while (k < amount)
		{
			zeroOnePack(k * cost, k * weight);
			amount = amount - k;
			k =<< 1;
		}
		zeroOnePack(amount * cost, amount * weight);
	}
}


本题:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define LL long long
#define lson lo, mi, rt << 1
#define rson mi + 1, hi, rt << 1 | 1

using namespace std;
const int maxv = 1e5 + 10;
const int maxn = 100 + 10;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = acos(-1.0);
const double ee = exp(1.0);

int n, m;
int value[maxn];
int amount[maxn];
int dp[maxv];

void zeroOnePack(int cost)
{
	for (int v = m; v >= cost; v--)
	{
		if (dp[v - cost] == 1)
		{
			dp[v] = 1;
		}
	}
}

void completePack(int cost)
{
	for (int v = cost; v <= m; v++)
	{
		if (dp[v - cost] == 1)
		{
			dp[v] = 1;
		}
	}
}

void multiplePack(int cost, int amount)
{
	if (m <= cost * amount)
	{
		completePack(cost);
	}
	else
	{
		int k = 1;
		while (k < amount)
		{
			zeroOnePack(k * cost);
			amount -= k;
			k <<= 1;
		}
		zeroOnePack(amount * cost);
	}
}

int main()
{
    #ifdef LOCAL
    freopen("in.txt", "r", stdin);
    #endif // LOCAL
    while (~scanf("%d%d", &n, &m))
    {
        if (!n && !m)
            break;
        for (int i = 1; i <= n; i++)
        {
        	scanf("%d", &value[i]);
        }
        for (int i = 1; i <= n; i++)
        {
        	scanf("%d", &amount[i]);
        }
        memset(dp, 0, sizeof(dp));
        dp[0] = 1;
        for (int i = 1; i <= n; i++)
        {
        	multiplePack(value[i], amount[i]);
        }
        int ans = 0;
        for (int i = 1; i <= m; i++)
        {
        	if (dp[i])
        	{
        		ans++;
        	}
        }
        printf("%d\n", ans);
    }
    return 0;
}



你可能感兴趣的:(动态规划)