01背包问题的优化解法
来源:互联网 发布:js点击变色再点击还原 编辑:程序博客网 时间:2024/06/02 13:57
01背包(ZeroOnePack):有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]}
把这个过程理解下:在前i件物品放进容量v的背包时,
它有两种情况:
第一种是第i件不放进去,这时所得价值为:f[i-1][v]
第二种是第i件放进去,这时所得价值为:f[i-1][v-c[i]]+w[i]
(第二种是什么意思?就是如果第i件放进去,那么在容量v-c[i]里就要放进前i-1件物品)
最后比较第一种与第二种所得价值的大小,哪种相对大,f[i][v]的值就是哪种。
(这是基础,要理解!)
这里是用二位数组存储的,可以把空间优化,用一位数组存储。
用f[0..v]表示,f[v]表示把前i件物品放入容量为v的背包里得到的价值。把i从1~n(n件)循环后,最后f[v]表示所求最大值。
*这里f[v]就相当于二位数组的f[i][v]。那么,如何得到f[i-1][v]和f[i-1][v-c[i]]+w[i]?(重点!思考)
首先要知道,我们是通过i从1到n的循环来依次表示前i件物品存入的状态。即:fori=1..N
现在思考如何能在是f[v]表示当前状态是容量为v的背包所得价值,而又使f[v]和f[v-c[i]]+w[i]标签前一状态的价值?
逆序!
这就是关键!
fori=1..N
forv=V..0
f[v]=max{f[v],f[v-c[i]]+w[i]};
分析上面的代码:当内循环是逆序时,就可以保证后一个f[v]和f[v-c[i]]+w[i]是前一状态的!
这里给大家一组测试数据:
测试数据:
10,3
3,4
4,5
5,6
这个图表画得很好,借此来分析:
C[v]从物品i=1开始,循环到物品3,期间,每次逆序得到容量v在前i件物品时可以得到的最大值。
- 01背包问题的优化解法
- 01 背包问题的另类解法
- 01背包问题的三种解法
- 01背包问题的动态规划解法
- 背包分组问题的解法
- 背包问题的解法源代码
- 背包问题的haskell解法
- 一种背包问题的解法
- 背包问题的递归解法
- 01背包问题(当有的背包重量是非整数时)的递归(优化成动态规划+再用滚动数组优化)解法
- 01背包问题的一维数组解法
- 01背包类型问题的两种解法
- 01背包的DFS解法
- 优化问题的matlab解法
- 最大公约数问题的优化解法
- 背包问题的遗传算法解法
- 背包问题的非递归解法
- P11: 背包问题的搜索解法
- 一致性hash算法 - consistent hashing
- 基于JVM的服务端javascript平台Ringo.js入门(四):stick-web框架使用
- Aligned malloc in C++
- 诺顿序列号获取方法
- C++编程获取本机所有ip地址 gethostbyname
- 01背包问题的优化解法
- Working Practice-依赖于制度体系而非员工的素质
- 复制schema
- Golang使用websocket
- MVC 模式简介
- 链表
- Linux-ASoC驱动归纳总结
- C++学习之旅——为什么要用虚函数
- CODE 79: Spiral Matrix