P06: 分组的背包问题
问题
有N件物品和一个容量为V的背包。第i件物品的费用是c
算法
这个问题变成了每组物品有若干种策略:是选择本组的某一件,还是一件都不选。也就是说设f[k][v]表示前k组物品花费费用v能取得的最大权值,则有:
f[k][v]=max{f[k-1][v],f[k-1][v-c
]+w |物品i属于组k}
使用一维数组的伪代码如下:
for 所有的组k for v=V..0 for 所有的i属于组k f[v]=max{f[v],f[v-cP05: 二维费用的背包问题
问题
二维费用的背包问题是指:对于每件物品,具有两种不同的费用;选择这件物品必须同时付出这两种代价;对于每种代价都有一个可付出的最大值(背包容量)。问怎样选择物品可以得到最大的价值。设这两种代价分别为代价1和代价2,第i件物品所需的两种代价分别为a
算法
费用加了一维,只需状态也加一维即可。设f
f
[v] =max{f[i-1][v] ,f[i-1][v-a ][u-b ]+w }
如前述方法,可以只使用二维的数组:当每件物品只可以取一次时变量v和u采用逆序的循环,当物品有如完全背包问题时采用顺序的循环。当物品有如多重背包问题时拆分物品。这里就不再给出伪代码了,相信有了前面的基础,你能够自己实现出这个问题的程序。
物品总个数的限制
有时,“二维费用”的条件是以这样一种隐含的方式给出的:最多只能取M件物品。这事实上相当于每件物品多了一种“件数”的费用,每个物品的件数费用均为1,可以付出的最大件数费用为M。换句话说,设f[v]
复数域上的背包问题
另一种看待二维背包问题的思路是:将它看待成复数域上的背包问题。也就是说,背包的容量以及每件物品的费用都是一个复数。而常见的一维背包问题则是实数域上的背包问题。(注意:上面的话其实不严谨,因为事实上我们处理的都只是整数而已。)所以说,一维背包的种种思想方法,往往可以应用于二位背包问题的求解中,因为只是数域扩大了而已。
#include <iostream>
#include <cmath>
using
namespace
std;
#define K 5
#define V 18
#define C 15
int
main(){
//初始化物品的价值,占用容积,花销
int
value[K] = {10, 20, 15, 18, 11};
int
volume[K] = {4, 7, 6, 5, 5};
int
cost[K] = {5, 6, 5, 5, 4};
//初始化dp用的数组
int
dp[V+1][C+1] = {0};
//dp每步都需要最优化
for
(
int
i = 0; i < K; i++)
for
(
int
j = V; j >= volume; j--)
for
(
int
k = C; k >= cost; k--)
dp[j][k] = max(dp[j][k], dp[j-volume][k-cost]+value);
cout<<dp[V][C]<<endl;
system
(
"pause"
);
}
第K大背包