01 背包
2016-05-19 18:52
232 查看
01背包
问题描述:给定 n 种物品和一背包,物品 i 的重量是 wi,其价值是 vi,背包容量为 c,问应如何选择装入背包中的物品,使装入背包中的物品价值最大?回溯法
在搜索解空间树时,只要其左儿子节点是一个可行节点,搜索就进入其左子树。当右子树中可能包含最优解时才进入右子树搜索。设 r 是当前剩余物品的价值总和;cv 是当前价值;max 是当前最优价值。当 cv + r <= max 时, 可减去右子树。void BackTrack(int cw, int cv, int i) { if (i > n) { max = cv; return; } if (cw + w[i] <= c) BackTrack(cw + w[i], cv + v[i], i + 1); if (cv + r[i + 1] > max) BackTrack(cw, cv, i + 1); } void Init() { for (int i = n; i >= 1; i--) r[i] = r[i + 1] + v[i]; }
动态规划(递推法)
正常的状态定义d(i,j) = max{d(i+1,j), d(i+1,j-W[i]) + V[i]}
d(i,j) 表示当前在第 i 层,背包剩余容量为 j 时的最大价值和,边界是 i > n 时 d(i,j) = 0;
for (int i = n; i >= 1; i--) for (int j = 0; j <= c; j++) { d[i][j] = (i == n ? 0 : d[i+1][j]); if (j >= W[i]) d[i][j] = max(d[i][j], d[i+1][j-W[i]] + V[i]); }
对称的状态定义
f(i,j) = max{f(i-1,j), f(i-1,j-W[i]) + V[i]}
f(i,j) 表示把前 i 个物品装到容量为 j 的背包中的最大价值和,边界是 i= 0 时 f(i,j) = 0;
for (int i = 1; i <= n; i++) for (int j = 0; j <= c; j++) { f[i][j] = (i == 1 ? 0 : f[i-1][j]); if (j >= W[i]) f[i][j] = max(f[i][j], f[i-1][j-W[i]] + V[i]); }
边读边计算, 不必把 V 和 W 保存下来
for (int i = 1; i <= n; i++) { scanf("%d%d", &V, &W); for (int j = 0; j <= c; j++) { f[i][j] = (i == 1 ? 0 : f[i-1][j]); if (j >= W) f[i][j] = max(f[i][j], f[i-1][j-W] + V); } }
滚动数组, 把数组 f 变成一维的
memset(f, 0, sizeof(f)); for (int i = 1; i <= n; i++) { scanf("%d%d", &V, &W); for (int j = 0; j <= c; j++) if (j >= W) f[j] = max(f[j], f[j-W] + V); }
相关文章推荐
- 库管理系统-- 后台管理开源啦,源码大放送
- 基础总结篇之七:ContentProvider之读写短消息
- 常量指针与指向常量的指针
- GDOI 2016 Day2 T1 SigemaGO
- Android技术积累:开发规范
- 高德地图组件在Android的应用以及Android与JavaScript的交互(二)
- 找水王
- Jedis对redis的操作详解
- crontab
- delegate,block,notification三者区别
- .NET Core R2
- Java问题总结33之利用UUID生成全局唯一码(Scala环境运行)
- Scala Standard Library API(01) -- scala.Any
- 单例
- Eclipse中设置作者,日期,版本等信息
- Redis+Spring缓存实例
- JSP的动作元素
- 第九次会议
- 基础总结篇之六:ContentProvider之读写联系人
- CSS中position的absolute如何相对于父元素的位置进行定位