1.问题描述

  给定n种物品和一个背包,物品i的重量是wi,其价值为vi,背包的容量为C。问:应该如何选择装入背包的物品,使得装入背包中物品的总价值最大?

2.问题分析

  上述问题可以抽象为一个整数规划问题,即求满足 (a)Σwixi ≤ C;(b)xi ∈(0,1),  1≤i≤n;条件下,∑vixi最大时的一个物品xi序列。分析问题可以发现,该问题具有最优子结构性质,那么就可以尝试用动态规划方法求解,而动态规划求解的关键就是列出问题的递归关系表达式。

  设m(i,j)为背包容量为j,可选物品为i,i+1,...n时0-1背包问题的最优质,那么可有如下递归式:

  m(i,j) = { max( m(i+1, j), m(i+1, j-wi)+vi);   j>=wi;

         { m(i+1, j);               j<wi;

要求的是m(1,c),此时问题就转化为填充m数组的问题了,以n = 5, c = 10, w[] = {2,2,6,5,4},v[] = {6,3,5,4,6},填充的过程如下图所所示,主要是用上述递归式求值,考虑当前物品能否放入,放入当前物品和不放入导致最终的价值哪个大,图中阴影部分为回溯求xi的过程,表示0,1,4号物品被放入背包中。

i/j 1 2 3 4 5 6 7 8 9 10
4 0 0 0 6 6 6 6 6 6 6
3 0 0 0 6 6 6 6 6 10 10
2 0 0 0 6 6 6 6 6 10 15
1 0 3 3 6 6 9 9 9 9 9
0 0 6 6 9 9 12 12 15 15 15

3.源码

  3.1 非递归

#include <stdio.h>#define N 1024
#define max(x, y) (x > y ? x : y)
#define min(x, y) (x < y ? x : y)void knapsack(int *w, int *v, int c, int n, int (*m)[N]);
void traceback(int *w, int (*m)[N], int *x, int n, int c);int main(int argc, const char *argv[])
{int n, c, w[N], v[N], m[N][N], x[N], i;scanf("%d%d", &n, &c);for(i = 0; i < n; i++)scanf("%d", &w[i]);for(i = 0; i < n; i++)scanf("%d", &v[i]);knapsack(w, v, c, n-1, m);      //这里传的是数组的最大下标traceback(w, m, x, n-1, c);     //求出是否装载的序列 x[i]printf("Max v: %d\n", m[0][c]);for(i = 0; i < n; i++)printf("x[%d] = %d\t", i, x[i]);printf("\n");return 0;
}void knapsack(int *w, int *v, int c, int n, int (*m)[N]){int j, jMax, i;jMax = min(w[n] - 1, c);for(j = 0; j <= jMax; j++)      //求m[n][]m[n][j] = 0;for(j = c; j > jMax; j--)m[n][j] = v[n];for(i = n-1; i > 0; i--){       //依次求m[n-1][] - m[1]jMax = min(w[i]-1, c);for(j = 0; j <= jMax; j++){m[i][j] = m[i+1][j];}for(j = c; j > jMax; j--){m[i][j] = max(m[i+1][j], m[i+1][j-w[i]] + v[i]);}}m[0][c] = m[1][c];              //求m[0][]if(w[0] < c){m[0][c] = max(m[1][c], m[1][c-w[0]] + v[0]);}
}void traceback(int *w, int (*m)[N], int *x, int n, int c){int i;for(i = 0; i < n-1; i++){if(m[i][c] == m[i+1][c])    //根据m数组 判断是否装进去x[i] = 0;else{x[i] = 1;c -= w[i];}}x[n] = (m[n][c] > 0) ? 1 : 0;
}

  3.2 递归

#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define N 5
#define C 10int w[] = {2, 2, 6, 5,4};           //使用递归 避免传递太多参数,不清晰
int v[] = {6, 3, 5, 4,6};           //因此设置成全局变量
int m[N][C], x[N];int knapsack(int i, int j);
void traceback();int main(int argc, const char *argv[])
{int i;knapsack(0, C);traceback();printf("Max :%d\n", m[0][10]);for(i = 0; i < N; i++)printf("x[%d] = %d\t", i, x[i]);printf("\n");return 0;
}int knapsack(int i, int j){if(i == N-1){m[i][j] = (j > w[i] ? v[i] : 0);return  m[i][j];}int ret1, ret2;if(j < w[i]){m[i][j] = knapsack(i+1, j);}else{ret1 = knapsack(i+1, j);ret2 = knapsack(i+1, j-w[i]) + v[i];m[i][j] =  ret1 > ret2 ? ret1 : ret2;}return m[i][j];}void traceback(){int i, n = N-1, c = C;for(i = 0; i < n; i++){if(m[i][c] == m[i+1][c])    //根据m数组 判断是否装进去x[i] = 0;else{x[i] = 1;c -= w[i];}}x[n] = (m[n][c] > 0) ? 1 : 0;
}

  3.3 书上有种改进的算法,采用跳跃点实现,暂时还没看懂,也许过两天在看就懂了呢。

转载于:https://www.cnblogs.com/monicalee/p/4012180.html

1008-----算法笔记----------0-1背包问题(动态规划求解)相关推荐

  1. 0/1背包问题-----动态规划求解

    问题描述 有n个物品和一个容量为c的背包,从n个物品中选取装包的物品.物品i的重量为w[i],价值为p[i].一个可行的背包装载是指,装包的物品总重量不超过背包的重量.一个最佳背包装载是指,物品总价值 ...

  2. 0/1背包问题——动态规划、回溯、分支限界法对比

    0/1背包问题--动态规划.回溯.分支限界法对比 2017.12.19 20:42:02 字数 3713 阅读 2820 目录 1.问题描述 1.1 问题描述 1.2 问题的数学表示(规划类问题,此种 ...

  3. 分支限界法 01背包c语言,算法笔记分支限界法01背包问题

    <算法笔记分支限界法01背包问题>由会员分享,可在线阅读,更多相关<算法笔记分支限界法01背包问题(12页珍藏版)>请在人人文库网上搜索. 1.问题描述给定n种物品和一背包.物 ...

  4. 0/1背包问题——动态规划方法

    1.定义 动态规划:把多阶段过程转化为一系列单阶段问题,利用各阶段之间的关系,逐个求解. 2.求解步骤 (1)找到状态转化条件 (2)归纳状态转移方程 (3)定义初始条件值 3.实例解析--0/1背包 ...

  5. 01背包问题 动态规划求解方法 动态方程的详细解释 能理解的解释(附python代码)

    01背包问题属于组合优化问题:假设你要出门旅游,你现在有一个书包,这个书包的容量(capacity)有限,有很多物品如牙刷.防晒霜.雨伞.水杯等等,但书包装不下所有物品,因此我们必须有所取舍.那么通常 ...

  6. 算法笔记:递归、动态规划

    目录 递归.分治和动态规划 德罗斯特效应 递归.分治和动态规划 迭代和递归的区别 分治 动态规划 解法 斐波那契数 解法1:暴力递归 解法2:记忆化存储 解法3:动态规划 解法4:自底向上迭代 动态规 ...

  7. 01背包问题—动态规划求解

    动态规划 01 背包问题 关键代码 for (int i = 1; i <= n; ++i){for (int j = 0; j <= c; ++j){if (j < w[i]) / ...

  8. 九章算法笔记D2-坐标型动态规划

    tags: 算法 DP 动态规划 大家觉得写还可以,可以点赞.收藏.关注一下吧! 也可以到我的个人博客参观一下,估计近几年都会一直更新!和我做个朋友吧!https://motongxue.cn 文章目 ...

  9. 0/1背包问题(蛮力法)

    问题描述: 给定n个重量为{w1,w2,w3,....,wn}.价值为{v1,v2,v3,...,vn}的物品和一个容量为C的背包,0/1背包问题是求解这些物品中的一个最有价值的子集,并且要能够装到背 ...

最新文章

  1. 普诺飞思获创新工场新一轮投资,加速神经拟态视觉传感技术商业化
  2. 如果要存 IP 地址,用什么数据类型比较好?大部人都会答错!
  3. 波士顿动力「全家」跳舞贺新年,马斯克点赞视频:这不是CG!
  4. 【运筹学】线性规划 单纯形法 阶段总结 ( 初始基可行解 | 判定最优解 | 迭代 | 得到最优解 | 全流程详细解析 ) ★
  5. python大神的成长之路_Python大神成长之路: 第二次学习记录
  6. python数据比例_知乎人均985?Python爬50W数据,BI做出可视化后,我有了答案
  7. CentOS 7 安装Golang
  8. ARM平台下独占访问指令LDREX和STREX的原理与使用详解
  9. 家门口的医疗新体验,网易云信携手嘉虹健康打造互联网医院新场景
  10. Matrix Power Series
  11. 那个抗血栓机器人_礼来抗血栓药物普拉格雷(Effient)不及波利维(Plavix)
  12. hash函数查找和ASL计算
  13. 无法从计算机中删除,【求助】Windows无法从该家庭组中删除你的计算机
  14. html与markdown互相转换
  15. 在Solaris 下使用Os Watcher 监控Oracle
  16. 在Excel表格中隐藏行或列
  17. 维斯易联网络打印机配置教程
  18. 可视化界面:Activity 详解
  19. [千峰安全篇9]Public Key Infrastructure
  20. 蓝懿学习之 疯狂阶段

热门文章

  1. POJ 3281 -- Dining(最大流,拆点建图)
  2. 第1-10个xhtml程序
  3. java加载xml配置文件_java读取配置文件的几种方法
  4. mysql字段说明_mysql 字段类型说明
  5. [BUUCTF-pwn]——wustctf2020_getshell
  6. oracle强大的包,ORACLE 程序包
  7. ZooKeeper安装过程
  8. 使用javassist动态注入代码
  9. vue生成包报错error from UglifyJs
  10. 关于最小化的另辟蹊径