博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
01背包问题内层循环必须是逆序的解释
阅读量:4283 次
发布时间:2019-05-27

本文共 916 字,大约阅读时间需要 3 分钟。

01背包问题的具体描述自行百度:

有N件物品和一个容量为V的背包。第i件物品的重量是c[i],价值是w[i]。

求解将哪些物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大。

(01背包中这些物品每种都只有1个,每个物品只能装一次)

基本问题

用子问题定义状态:即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。
则其状态转移方程便是:f[i][v]=max{ f[i-1][v], f[i-1][v-c[i]]+w[i] }。可以压缩空间,f[v]=max{f[v],f[v-c[i]]+w[i]}

这个方程非常重要,基本上所有跟背包相关的问题的方程都是由它衍生出来的。所以有必要将它详细解释一下:

“将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题。

如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中”,价值为f[i-1][v];如果放第i件物品,

那么问题就转化为“前i-1件物品放入剩下的容量为v-c[i]的背包中”,

此时能获得的最大价值就是f [i-1][v-c[i]]再加上通过放入第i件物品获得的价值w[i] 即f[i-1][v-c[i]]+w[i]。

为什么逆序

逆序的关键就在于这个状态转移方程

f[i][v]只与f[i-1][v]和f[i-1][v-C[i]]有关,即只和i-1时刻状态有关,所以我们只需要用一维数组f[]来保存i-1时的状态f[]。
假设i-1时刻的f[]为{a0,a1,a2,…,av},那么i时刻的f[]中第v个应该为max(av,av-C[i]+W[i])即max(f[v],f[v-C[i]]+W[i]),

这就需要我们遍历V时逆序遍历,这样才能保证求i时刻f[v]时f[v-C[i]]是i-1时刻的值。如果正序遍历则当求f[v]时
其前面的f[0],f[1],…,f[v-1]都已经改变过,里面存的都不是i-1时刻的值,这样求f[v]时利用f[v-C[i]]必定是错的值。最后f[V]即为最大价值。

数组遍历有时候必须逆序大多是这个原因。

转载地址:http://hlcgi.baihongyu.com/

你可能感兴趣的文章
Java基础教程
查看>>
JSP基础教程
查看>>
系统设计概论
查看>>
springboot打包
查看>>
centos7安装redis
查看>>
centos7防火墙命令
查看>>
springboot搭建Eureka注册服务器,application启动报错
查看>>
在tiny6410移植rt5370驱动
查看>>
nyoj-754--黑心医生
查看>>
hdu-超级密码(BFS)
查看>>
线性筛选素数法(O(n)复杂度)
查看>>
nyoj-222 整数中的1
查看>>
nyoj-619 青蛙过河
查看>>
hdu-2199 Can you solve this equation?(二分+精度)
查看>>
hdu-4510 小Q系列故事——为什么时光不能倒流(比赛被虐的一道水题)
查看>>
c++课程设计
查看>>
nyoj-小明的密钥(362)--数论
查看>>
hdu-3790最短路径问题
查看>>
UVa-10341
查看>>
zoj-1789
查看>>