文章目录

  • 1 问题描述
  • 2 基本原理
  • 3代码实现

1 问题描述

有n个物品,它们有各自的重量和价值,现有一给定最大载重的背包,如何让背包里装入的物品具有最大的价值总和而又不超过最大载重?
比如:

商品 1 2 3 4 5
重量 1 2 3 4 5
价值 3 4 5 6 7

假设背包最大载重为8,可以求得以下两种最优方案

商品1 商品2 商品5
总价值:14
总重量:8 <= 最大载重

商品1 商品3 商品4
总价值:14
总重量:8 <= 最大载重

2 基本原理

定义数组V[0…n][0…maxWeight]

其中,n表示商品的总数,maxWeight表示背包的最大载重量。

定义V[i][w]为包含前i件商品最大载重为w时的子问题的最优方案的总价值

只需要讨论当前商品i是否可能在当前子问题的最优方案中便可以得到以下递推式:

若 weigth[i] > w, 即当前商品i太重了,故不可能出现在当前子问题的最优方案里,因此
V[i][w] = V[i-1][w]

//若 weigth[i] <= w ,则说明当前商品i可能在当前子问题的最优方案中,因此需要做比较选择,故有
V[i][w] = max( V[i-1][w] , V[i-1][w-weigth[i]] + value[i] )

3代码实现

利用上面的递推式便能使用动态规划算法解决问题!
c++代码如下:

//Albert Chow 2020.08.30
# include <iostream>
using namespace std;/***********************************************************************************/
//用于动态创建二维数组
//利用了模板
template<typename T>
T** buildArray2D(int row, int column)
{T* p = new T[row * column]; //开辟一片临时空间T** a = new T * [row];       //创建行指针for (int i = 0; i < row; i++){a[i] = p + column * i;     //给行指针赋值}return a;};template<typename T>
void deleteArray2D(T** a)
{delete[] * a;delete[] a;
}
/***********************************************************************************///0-1背包问题算法//简单版本,用于理解算法
int knapsack_0_1_v1(int n, int* weigth, int* value, int maxWeight)
{int** V = buildArray2D<int>(n+1, maxWeight+1); //动态创建一个二维数组//其中A[i][w] 表示 包含前i件商品,最大重量为w时的子问题的最大价值//因此可分最优方案包不包含当前商品i而得到如下的递推式://若 weigth[i] > w, 即当前商品i太重了,故不可能出现在当前子问题的最优方案里,因此//V[i][w] = V[i-1][w]//若 weigth[i] <= w ,则说明当前商品i可能在当前子问题的最优方案中,因此需要做比较选择//V[i][w] = max(  V[i-1][w]  ,  V[i-1][w-weigth[i]] + value[i]  )//根据以上的递推式设计自底向上的dp算法如下:int i,w;//对V做下初始化for (w = 0; w <= maxWeight; w++)V[0][w] = 0;for (i = 1; i <= n; i++)V[i][0] = 0;for(i = 1;i<=n;i++)for (w = 1; w <= maxWeight; w++){if (weigth[i -1] > w)    //当前商品大于背包容量时的递推式{V[i][w] = V[i - 1][w];  }else     //当前商品可能出现在最优解里面的递推式{//V[i][w] = max(  V[i-1][w]  ,  V[i-1][w-weigth[i]] + value[i]  )//注意cpp中数组下标从0开始if ( V[i - 1][w] > (V[i - 1][w - weigth[i - 1]] + value[i - 1]) ){V[i][w] = V[i - 1][w];}else{V[i][w] = V[i - 1][w - weigth[i - 1]] + value[i - 1];}}}int res = V[n][maxWeight];deleteArray2D<int>(V);//手动释放内存return res;
}//原理同v1,只是在内存上作了优化
int knapsack_0_1_v2(int n, int* weigth, int* value, int maxWeight)
{int* V = new int[maxWeight + 1];int i, w;//对V做下初始化for (w = 0; w <= maxWeight; w++)V[w] = 0;for (i = 1; i <= n; i++)//为了防止数据覆盖,这里w采用逆序//由于w < weigth[i - 1]时 无需更新数组,因此w的遍历只到weigth[i - 1]for (w = maxWeight; w >= weigth[i - 1]; w--)  {     if (V[w - weigth[i - 1]] + value[i - 1] > V[w]){V[w] = V[w - weigth[i - 1]] + value[i - 1];}}int res = V[maxWeight];delete[] V;return res;
}//定义一个结构体,用于函数返回多个变量
typedef struct
{int val;bool** choice;
} RES;//原理同v1,只是为重现最优解做了一些修改
RES knapsack_0_1_v3(int n, int* weigth, int* value, int maxWeight)
{int** V = buildArray2D<int>(n + 1, maxWeight + 1); //动态创建一个二维数组bool **choice = buildArray2D<bool>(n, maxWeight);int i, w;//对V做下初始化for (w = 0; w <= maxWeight; w++)V[0][w] = 0;for (i = 1; i <= n; i++)V[i][0] = 0;for (i = 1; i <= n; i++)for (w = 1; w <= maxWeight; w++){if (weigth[i - 1] > w)    //当前商品大于背包容量时的递推式{V[i][w] = V[i - 1][w];choice[i -1][w -1] = 0;  //注意c语言下标从0开始}else     //当前商品可能出现在最优解里面的递推式{//V[i][w] = max(  V[i-1][w]  ,  V[i-1][w-weigth[i]] + value[i]  )//注意cpp中数组下标从0开始if (V[i - 1][w] > (V[i - 1][w - weigth[i - 1]] + value[i - 1])){V[i][w] = V[i - 1][w];choice[i - 1][w - 1] = 0;}else{V[i][w] = V[i - 1][w - weigth[i - 1]] + value[i - 1];choice[i - 1][w - 1] = 1;}}}RES res;res.val = V[n][maxWeight];res.choice = choice;//手动释放内存deleteArray2D<int>(V);return res;
}//原理同v2,只是为重现最优解做了一些修改,注意多与v3对比
RES knapsack_0_1_v4(int n, int* weigth, int* value, int maxWeight)
{int* V = new int[maxWeight + 1];bool** choice = buildArray2D<bool>(n, maxWeight);int i, w;//对V做下初始化for (w = 0; w <= maxWeight; w++)V[w] = 0;for (i = 1; i <= n; i++){//为了防止数据覆盖,这里w采用逆序//由于w < weigth[i - 1]时 无需更新数组,因此w的遍历只到weigth[i - 1]for (w = maxWeight; w >= weigth[i - 1]; w--){if (V[w - weigth[i - 1]] + value[i - 1] > V[w]){V[w] = V[w - weigth[i - 1]] + value[i - 1];choice[i - 1][w - 1] = 1;}elsechoice[i - 1][w - 1] = 0;}for (w = weigth[i - 1]-1; w>=1; w--)  //补零choice[i -1][w -1] = 0;}RES res;res.val = V[maxWeight];res.choice = choice;delete[] V;return res;
}//仿照算法导论p225的程序得到的
void printKnapsack(bool** choice, int *weight,int i,int w)
{if (i == 0 || w == 0)return;if (choice[i -1][w -1] == 1){printKnapsack(choice, weight,  i - 1,  w - weight[i - 1] );cout << "商品" << i << " ";}else{printKnapsack(choice, weight, i - 1, w);}
}int main()
{//可以自己修改数据验证算法是否正确// 1  2  3  4  5  6  7  8   9   10int weight[]  = {1, 2, 3, 4, 5};int value[]   = {3, 4, 5, 6, 7};int n = sizeof(weight)/sizeof(weight[0]);int maxWeight = 8;/************************************************************************/int r1 = knapsack_0_1_v1(n,weight, value, maxWeight);cout << r1 << endl;int r2 = knapsack_0_1_v2(n, weight, value, maxWeight);cout << r2 << endl;RES r3 = knapsack_0_1_v3(n, weight, value, maxWeight);cout << r3.val << endl;printKnapsack(r3.choice, weight, n, maxWeight);deleteArray2D<bool>(r3.choice);cout << endl;RES r4 = knapsack_0_1_v4(n, weight, value, maxWeight);cout << r4.val << endl;printKnapsack(r4.choice, weight, n, maxWeight);deleteArray2D<bool>(r4.choice);cout << endl;return 0;
}

0-1背包问题(0-1 knapsack problem)c++实现相关推荐

  1. 动态规划法(四)0-1背包问题(0-1 Knapsack Problem)

      继续讲故事~~   转眼我们的主人公丁丁就要离开自己的家乡,去大城市见世面了.这天晚上,妈妈正在耐心地帮丁丁收拾行李.家里有个最大能承受20kg的袋子,可是妈妈却有很多东西想装袋子里,已知行李的编 ...

  2. Knapsack Problem

    背包九讲 0-1 knapsack problem 01背包-牛客网 已知一个背包最多能容纳体积之和为V的物品,现有 n 个物品,第 i 个物品的体积为 vi , 重量为 wi,求当前背包最多能装多大 ...

  3. [Algorithmic Toolbox学习笔记][week6]0/1 Knapsack Problem

    问题描述 具体的问题描述请参考以下链接: [Algorithmic Toolbox学习笔记][week3]战利品的最大价值_Karen_AMPM的博客-CSDN博客假设小偷有一个背包只能放下一定重量的 ...

  4. Dynamic Programming 01 —knapsack problem(动态规划背包问题)

    首先引入动态变化的含义:为什么要有动态规划? Introduction: 从斐波那契函数的递归中我们发现,在例子求fib(7)的过程中,我们需求得fib(5)和fib(6),而我们在求fib(6)的时 ...

  5. C#,背包问题(Knapsack Problem)贪心算法的源代码

    背包问题(KnapSack Problem)的相关算法是常用的规划算法. 一.什么是背包问题? 背包的问题是,你有一个"袋子",可以装有限数量的物品,鉴于你有一组物品可以从每个物品 ...

  6. 算法设计与分析实验二:动态规划法实现TSP问题和0/1背包问题

    [实验目的] 1.熟练掌握动态规划思想及教材中相关经典算法. 2.使用动态规划法编程,求解0/1背包问题和TSP问题. TSP问题 一.实验内容: TSP问题是指旅行家要旅行n个城市,要求每个城市经历 ...

  7. Python多维约束(重量+体积+次数)背包问题(Knapsack Problem)

    问题描述:1.一个背包,往里装东西,物品重量w(weight)对应为[2,3,4,7] ,价值va(value)对应为[1,4,7,12] ,如果你的最大承重为20,每个物品可装次数不限,求你能装入背 ...

  8. 0/1背包问题---C++动态规划法

    [问题] 给定n种物品和一个背包,物品i(1≤i≤n)的重量是,其价值为,背包容量为,对于每种物品只有两种选择:装入背包或者不装入背包.如何选择装入背包的物品,使得装入背包中物品的总价值最大? [想法 ...

  9. C语言动态规划法解决0/1背包问题(详细解答)

    动态规划法解决0/1背包问题(详细解答) 首先让我们回顾一下动态规划法的使用规则: 一..动态规划法的实现思路: 1.划分子问题:将元问题分解为若干个子问题,每一个子问题对应一个决策,并且子问题之间具 ...

最新文章

  1. SSRS配置2:加密管理
  2. Openstack-M版(双节点)热迁移记录
  3. 关于图片按比例自适应缩放
  4. 记录 关于浏览器跨域和设置默认浏览器的问题
  5. 边框回归的损失函数_分类损失函数,边框回归损失函数
  6. 邹建老大写的经典SQL
  7. top-1和top-5正确率与错误率以及目标检测评价指标
  8. 用户与组管理,磁盘管理
  9. 四个DBHelper实现
  10. python ffmpeg剪辑视频_FFMPEG剪辑大法
  11. mumu模拟器Android版本才6,mumu模拟器老版本
  12. 《自然语言处理简明教程》读书笔记:第十四章 文本数据挖掘
  13. 传输线模式<TEM TE TM EH HE>
  14. SysAnti.exe和autorun.inf病毒的查杀
  15. CSS3炫酷的发光文字 可自定义文字色彩
  16. 如何在地图上显示多个红包商店 vue
  17. 在线制作平台H5制作
  18. 【设计模式】工厂模式(Factory Pattern)
  19. 基于Springboot+Mybatisplus+Vue的科研项目管理系统
  20. centos8操作系统初始化设置

热门文章

  1. linux网络操作系统电大考试,国开2020年秋《linux网络操作系统》形考任务题库大全...
  2. 16m色真彩调色板设计制作
  3. 【无标题】ubuntu添加文件到mkinitramfs命令生成的initramfs中
  4. 使用c#实现爬虫技术
  5. android的定位(2)
  6. 查看QQ是否隐身,轻而易举。 - [工具+源码]
  7. 实验四 数码管显示设计与仿真
  8. 【NLP+图神经网络+推荐领域】2020年最新综述性文章推荐
  9. Pandas单层索引多层索引
  10. Google面对点击欺诈拷问 广告主拟诉诸法律