多重背包:经典DP问题( 基本/二进制优化/单调队列优化 )

    多重背包问题描述:介于01背包和完全背包问题之间,每种物品的最大选取数目都是已知的。

    对于一定数量( i )的物品有一个容量为( j )的背包,每个物品都有自己的容量( k )、价值(value)和数目( cnt )。在保证物品容量之和不大于背包容量的前提下,如何选取物品得到最大价值?

    状态转移方程可以稍微修改完全背包问题的得到,dp[ind][jnd]=Max(dp[ind-1][jnd-knd*k]+knd*value,dp[ind-1][jnd]),原方程不变,需要改的是knd的范围,完全背包每个物品的个数是无限个,knd仅需要满足knd*k<=jnd。现在每个物品有了自己的最大数目( cnt ),也就是说还需要满足knd<=cnt。

    经过上面的推论,在 jnd<k 时,dp[ind][jnd]=dp[ind-1][jnd] ;jnd>=k时,dp[ind][jnd]=Max(dp[ind-1][jnd-knd*k]+knd*value,dp[ind-1][jnd]) | knd<=cnt | knd*k<=jnd 。

#include<stdio.h>
#define Max(a,b) (a>b?a:b)
int dp[1005][10005];
int k[1005], value[1005], cnt[1005];
int main(int argc, char* argv[])
{
	int i, j, s;
	scanf("%d %d", &i, &j);
	for (int ind = 1; ind <= i; ++ind)
		scanf("%d %d %d", &k[ind], &value[ind], &cnt[ind]);
	for (int ind = 1; ind <= i; ++ind)
	{
		for (int jnd = 1; jnd <= j; ++jnd)
		{
			if (jnd - k[ind] < 0)
				dp[ind][jnd] = dp[ind - 1][jnd];
			else
			{
				s = dp[ind - 1][jnd];
				for (int knd = 1; knd*k[ind] <= jnd && knd <= cnt[ind]; knd++)
					s = Max(s, dp[ind - 1][jnd - knd * k[ind]] + knd * value[ind]);
				dp[ind][jnd] = s;
			}
		}
	}
	printf("%d\n", dp[i][j]);
	return 0;
}

    不经优化的状态转移方程直接求解时间复杂度太高,大多需求都不能满足。考虑能不能通过什么方法

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define Max(a,b) (a>b?a:b)
#define ArrayMax 10005
int dp[ArrayMax];
int main(int argc, char* argv[])
{
	int i, j;
	scanf("%d %d", &i, &j);
	while (i--)
	{
		int k, value, cnt;
		int now = 1;
		scanf("%d %d %d", &k, &value, &cnt);
		if (cnt*k > j)
		{
			for (int ind = k; ind <= j; ind++)
				dp[ind] = Max(dp[ind - k] + value, dp[ind]);
		}
		else
		{
			while (1)
			{
				if (cnt > now)
				{
					cnt -= now;
					for (int ind = j; ind >= k * now; ind--)
						dp[ind] = Max(dp[ind - k * now] + now * value, dp[ind]);
					now *= 2;
				}
				else
				{
					now = cnt;
					for (int ind = j; ind >= now * k; ind--)
						dp[ind] = Max(dp[ind - now * k] + now * value, dp[ind]);
					break;
				}
			}
		}
	}
	printf("%d\n", dp[j]);
	return 0;
}
(草稿)

猜你喜欢

转载自blog.csdn.net/belous_zxy/article/details/80357450