java多重背包算法,01背包、完全背包和多重背包

最优化原理

指的最优策略具有这样的性质:不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略。

如何证明一个最优策略的子策略也是最优解,一般使用反证法来证明。

无后效性

指的是某状态下决策的收益,只与状态和决策相关,与到达该状态的方式无关。某个阶段的状态一旦确定,则此后过程的演变不再受此前各种状态及决策的影响。

将问题扩展到一般情况。为了实现这个目的,我们需要将问题进行抽象并建模,然后将其划分为更小的子问题,找出递推关系式,这是分治思想中很重要的一步。

问题1:你只有一个容量有限的背包,总容量为c,有n个可待选择的物品,每个物品只有一件,它们都有各自的重量和价值,你需要从中选择合适的组合来使得你背包中的物品总价值最大。

为了求解这个问题,我们把这个问题用数学的方式表达出来。

n个可待选择的物品,重量分别为w1,w2,w3……wn;价值分别为v1,v2,v3……vn;

我们可以拿或者不拿这个物品,用x1,x2,x3……xn来表示是否拿取的操作。

对于数到其中的一个i,求解当前阶段中的最大价值maxV=max(v1x1+v2x2+...+vixi)

约束条件为w1x1+w2x2+...+wixi

定义函数 fun(i,j)当前容量为j的情况下,前i个物品的组合组成最大值。

有两种情况:

1背包已经装不下这个石头了,所以 fun(i,j) = fun(i-1,j)

2背包可以装下这个石头,但是并不一定是最优值。

如果不装的话fun(i,j) = fun(i-1,j)

如果装的话fun(i,j) = fun(i-1,j - wi) + vi

max(fun(i-1,j) , fun(i-1,j - wi) + vi)

问题到这里其实使用递归解法已经能解出答案了,但是在一些数据量非常大的时候会导致内存超出,为了解决这个问题——>自上而下的解法与分治法的区别就是增加了一个数组用来存储计算的中间结果来减少重复计算。这里,我们只需要多定义一个二维数组。

3af47b1c8501

采用自上而下填表法,可以发现很多计算是多余的,只需要在递归的过程中存储下计算的答案,就把问题的复杂度转化为了二维数组,空间复杂度为(n*c)。

问题2:有N种物品和一个容量为T的背包,每种物品都就可以选择任意多个,第i种物品的价值为P[i],体积为V[i],求解:选哪些物品放入背包,可使得这些物品的价值最大,并且体积总和不超过背包容量。

完全背包的解题逻辑和01背包的解题逻辑差距只在(在选取第i个物体时,需要遍历当前剩余体积下选取几个第i个物体,选取几个第i个物品后的价值和当前剩余体积下所求解出的最大的值的和中挑选最大的值作为此子问题的最优解)

ks(i,t) = max{ks(i-1, t - V[i] * k) + P[i] * k}; (0 <= k * V[i] <= t)

问题3:有N种物品和一个容量为T的背包,第i种物品最多有M[i]件可用,价值为P[i],体积为V[i],求解:选哪些物品放入背包,可以使得这些物品的价值最大,并且体积总和不超过背包容量。

ks(i,t) = max{ks(i-1, t - V[i] * k) + P[i] * k}; (0 <= k <= M[i] && 0 <= k * V[i] <= t)

解析多重背包的问题,其实和完全背包的问题很像,对比两个状态方程可以看到,区别仅仅在于k的取值范围上。

在计算量上来说,其实多重背包的计算过程比完全背包更短。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值