您的位置:首页 > 其它

背包问题1:01背包

2015-10-11 20:37 267 查看
有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。

这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。

用子问题定义状态:即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。

则其状态转移方程便是:f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]};

伪代码如下:

for i = 1...N

for v = 0...V

f[i][v] = max(f[i-1][v], f[i-1][v-c[i]] + w[i]);

优化1:可在两层循环中直接输入c[i],w[i],而不需要进行保存。

优化2:考虑到f[i+1]只是直接依赖于f[i],类比优化一,并且f[v]依赖于f[v-c[i]],由此得到改进如下:

for i=1..N

    for v=V..0

        f[v]=max{f[v],f[v-c[i]]+w[i]};

当f[v]直接取f[v]时对应的是没有取第i个物品,反之则取了。初始化f[]数组为0,相当于对于前0个物品,最大价值都为0,成立。

01背包问题的算法在更复杂的背包问题中将用到,现将其封装为:

procedure ZeroOnePack(cost,weight)

    for v=V..cost

        f[v]=max{f[v],f[v-cost]+weight}

即决策是否要选择该物品。
如此调用:

for i = 1...N

ZeroOnePack(c[i],w[i]);

初始化的细节:

当要求恰好装满背包时,可以将f[0]初始化为0,而其他f[1...V]均设置为-∞,由此当f[V]算得为负时候其实是没有正确答案的。

也可以将除f[0]外f[1...V]全部设置为-1,每次如果f[v]或f[v-c]为-1,则对相应状况不做处理,因为-1表示的是未定义状态。

(看 《背包九讲》 的心得)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  01背包