让你不可能看不明白的0-1背包代码
一、首先搞懂,什么是动态规划?
所谓动态规划,dynamic programming以我的短见来看不必看的太过复杂,名字的确霸气,但实际的基础应用中更像递归的高级版
能使用动态规划的问题有如下三个特征:
(1) 最优化原理:如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构,即满足最优化原理。
(2) 无后效性:即某阶段状态一旦确定,就不受这个状态以后决策的影响。也就是说,某状态以后的过程不会影响以前的状态,只与当前状态有关。
(3)有重叠子问题:即子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到。(该性质并不是动态规划适用的必要条件,但是如果没有这条性质,动态规划算法同其他算法相比就不具备优势)
动态规划的解决思路:为由于整体过程直接解决过于复杂,因此把问题分割成无数小问题,在每一个小问题里得到局部最优解,因为每一步都是当下的最优解,一直递归得到的就是最终的最优解;

初始状态→│决策1│→│决策2│→…→│决策n│→结束状态
二、代码步骤详解(附完整简洁代码)
1 #include <iostream> 2 using namespace std; 3 #define C 18 //背包容量 4 #define N 7 //物品种类为6 5 //默认下标从1开始 6 int w[N] = {0, 2, 9, 8, 6, 10, 8}, //物品重量 7 v[N] = {0, 9, 3, 18, 11, 7, 12}, //物品价值 8 m[N][C] = {0}; //每一个小网格的最优解 9 //容量c 种类n 子背包容量j 10 // Knapsack:子背包 11 void Knapsack(int c, int n) 12 { 13 int jMax = w[n] - 1 < c ? w[n] - 1 : c;//这里jMax的值作用是看能不能放下,也算是剪枝了 14 for (int j = 0; j <= jMax; j++)//置空前面因为放不下哈哈 15 m[n][j] = 0; 16 for (int j = w[n]; j <= c; j++)//从8开始到18, 17 m[n][j] = v[n];//最后一行全变为12,假设一个容量为w[n] 18 for (int i = n - 1; i > 1; i--) // i从最后一个开始往回,不断判断各个物品,最后i=1时不必判断,只要判断放不放即可 19 { 20 jMax = w[i] - 1 < c ? w[i] - 1 : c;//jMax为w[i]-1和c中小的那个,看第i件物品是不是能放进背包 21 //初始化,因为i从最后一件物品往回遍历,默认把下面的网格最优解先拷贝了 22 for (int j = 1; j <= jMax; j++) 23 m[i][j] = m[i + 1][j]; 24 //判断 25 for (int j = w[i]; j <= c; j++) 26 m[i][j] = m[i + 1][j] > m[i + 1][j - w[i]] + v[i] ? m[i + 1][j] : m[i + 1][j - w[i]] + v[i]; 27 } 28 m[1][c] = m[2][c]; 29 if (c >= w[1]) 30 m[1][c] = m[1][c] > m[2][c - w[1]] + v[1] ? m[1][c] : m[2][c - w[1]] + v[1]; 31 } 32 // 算法的时间复杂度为O(nc) 33 34 //回溯 35 void Traceback(int c, int n, int x[]) 36 { 37 //这里所谓回溯不过是从头看一遍都放了哪几个,因为从下往上规划,最上面的是最优的 38 for (int i = 1; i < n; i++) 39 if (m[i][c] == m[i + 1][c]) 40 x[i] = 0; 41 else 42 { 43 x[i] = 1; 44 c -= w[i]; 45 } 46 x[n] = m[n][c] > 0 ? 1 : 0; 47 } 48 49 int main() 50 { 51 int x[N] = {0}; 52 Knapsack(C, N - 1); 53 Traceback(C, N - 1, x); 54 cout<<endl<< " C=\t" << C << endl<< " x:\t"; 55 int w1 = 0, v1 = 0; 56 for (int i = 1; i < N; i++) 57 { 58 cout << x[i] << '\t'; 59 w1 += x[i] * w[i]; 60 v1 += x[i] * v[i]; 61 } 62 cout << endl 63 << "Weight=\t" << w1 << endl; 64 cout << "Value=\t" << v1 << endl 65 << endl; 66 }

浙公网安备 33010602011771号