动态规划:0-1背包问题
2017-05-10 21:01
197 查看
0-1背包问题是比较经典的动态规划,题意如下:
给定n件物品的重量和对应价值,给定一个背包的最大承重,求该背包所能装下的物品的最大价值,并输出哪几件装进了背包。
这个问题可以用一个二维数组来做,这样非常直观明了。但是有些情况下,数据过大,采用二维数组会超空间,所以需要采用一维数组进行空间压缩,复杂度是不变的,要注意的是填充一维数组时需要倒序。每次更新一遍一维数组,其实就相当于二维数组的更新。
下面是二维数组的方法,一维数组的方法在其后:
最关键的一个公式是
d[i][j] = max(d[i - 1][j], d[i - 1][j - w[i]] + v[i]);
其中,d[i][j]是指在前i件物品中,选择若干件放在承重为j的背包中,可以取得的最大价值。
先给出d[i][j]这个矩阵的示意图,因为我觉得在编程实现
过程中一直想着这个矩阵,思路会清晰很多。
![](https://img-blog.csdn.net/20170510215246425?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSUJlbGlldmUyMDE2/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
这里,我统一把数组的第0个元素置为零,不使用(即:在上面的矩阵中,第0列全是0,不使用,就没有画出来。数组中的1就代表第一个)
代码如下,注释说的很清楚了:
填充一个一维数组的过程其实就是更新N遍,第i遍更新相当于上面的前i个物品容量不同时的最大价值。
下面是代码:
给定n件物品的重量和对应价值,给定一个背包的最大承重,求该背包所能装下的物品的最大价值,并输出哪几件装进了背包。
这个问题可以用一个二维数组来做,这样非常直观明了。但是有些情况下,数据过大,采用二维数组会超空间,所以需要采用一维数组进行空间压缩,复杂度是不变的,要注意的是填充一维数组时需要倒序。每次更新一遍一维数组,其实就相当于二维数组的更新。
下面是二维数组的方法,一维数组的方法在其后:
最关键的一个公式是
d[i][j] = max(d[i - 1][j], d[i - 1][j - w[i]] + v[i]);
其中,d[i][j]是指在前i件物品中,选择若干件放在承重为j的背包中,可以取得的最大价值。
先给出d[i][j]这个矩阵的示意图,因为我觉得在编程实现
过程中一直想着这个矩阵,思路会清晰很多。
这里,我统一把数组的第0个元素置为零,不使用(即:在上面的矩阵中,第0列全是0,不使用,就没有画出来。数组中的1就代表第一个)
代码如下,注释说的很清楚了:
#include <iostream> #include<algorithm> using namespace std; //d[i][j]是一个矩阵,表示在前i件物品中,选择若干件放在承重为j的背包中,可以取得的最大价值 int main(){ int w[6] = {0, 2, 2, 6, 5, 4 }; //6件物品的重量 int v[6] = {0, 6, 3, 5, 4, 6 }; //6件物品的价值 int c = 10; //背包的最大承重量 int a[6] = { 0 }; //用来存储第i个物品是否装入背包 int d[6][11] = { 0 }; //矩阵 //接下来的双层for循环,用来填充矩阵 for (int< 4000 /span> j = 0; j <= 10; j++) d[0][j] = 0; for (int i = 1; i <= 5; i++){ for (int j = 0; j <= 10; j++) { if (j < w[i]){ //如果背包装不了第i件,最大价值相当于和第i-1件的时候一样 d[i][j] = d[i - 1][j]; } else{ d[i][j] = max(d[i - 1][j], d[i - 1][j - w[i]] + v[i]); //这个公式是核心! } } } //接下来的for循环,用来回溯,找到哪个物品放入了背包 int j = 10; for (int i = 5; i > 0; i--){ //如果第i个和第i-1个不一样,说明第i个加进来了 if (d[i][j] > d[i - 1][j]){ a[i] = 1; j = j - w[i]; } else a[i] = 0; } cout << d[5][10] << endl; for (int i = 1; i <= 5; i++) cout << a[i] << " "; cout << endl; return 0; }
填充一个一维数组的过程其实就是更新N遍,第i遍更新相当于上面的前i个物品容量不同时的最大价值。
下面是代码:
#include <iostream> #include <algorithm> #include <cstring> #include <stdio.h> using namespace std; int main(){ int w[6] = { 0, 2, 2, 6, 5, 4 }; //6件物品的重量 int v[6] = { 0, 6, 3, 5, 4, 6 }; //6件物品的价值 int c = 10; //背包的最大承重量 int dp[11] = { 0 }; for (int i = 0; i < 6; i++){ for (int j = c; j >= w[i]; j--){ //对这个数组倒序填充 dp[j] = max(dp[j], dp[j - w[i]] + v[i]); } } cout << dp[c] << endl; return 0; }
相关文章推荐
- 01背包问题动态规划详解(转载)
- 0/1背包问题动态规划详解(转)
- 动态规划_背包问题扩展
- 0/1背包问题动态规划详解之一
- 动态规划:0-1背包问题(使用递归方法)
- 0-1背包问题的动态规划解法为什么是NPC问题?
- 动态规划_背包问题基础
- 0-1背包问题的动态规划解法
- 01背包问题动态规划详解
- 0/1背包问题动态规划详解
- 0/1背包问题动态规划详解
- 动态规划 和 背包问题的一个讲座
- 动态规划解0-1背包问题
- 动态规划解决0-1背包问题
- 开始学习动态规划---先解决下背包问题
- 0/1背包问题动态规划详解
- 背包问题动态规划详细探究
- 0-1背包问题动态规划
- 背包问题动态规划求解
- 动态规划解背包问题/C++/Knapsack problem