背包九讲-01背包
tianyi cui 的背包九讲老版本:http://love-oriented.com/pack/,
新版pdf下载地址2:http://download.csdn.net/detail/tangzhangpeng/5591321
本文实现了新版本第一章 “01背包问题”,代码中的注释也是针对新版本。
pdf 1.5 小节中的小错误,常数优化应该是
,对Ci求和而不是对Wi求和
对1.5常数优化的解释:前 i 个物品获得的空间最小值是:,即后面i~N个物品装满后剩余的空间,若剩余空间小于Ci,则为Ci
算法测试数据来自:http://www.cnblogs.com/jisi5789/archive/2013/04/11/3015745.html
相关代码如下:
1 #include<iostream> 2 #include<string> 3 #include<vector> 4 using namespace std; 5 6 inline int max(int a, int b) 7 { 8 return a>b?a:b; 9 } 10 11 int ZeroOnePack1(int n, int v, int c[], int w[], bool needFull) 12 { 13 //根据tianyi cui背包九讲1.2的最原始的解法 14 //时间空间复杂度均为O(nv) 15 // n 物品数量 16 // v 背包容量 17 // c[] 物品耗费的空间,从c[1]开始 18 // w[] 物品的价值,从w[1]开始 19 // needFull 背包是否需要完全装满 20 const int MIN = numeric_limits<int>::min(); //表示负无穷 21 int **f = new int*[n+1]; 22 for(int i = 0; i < n+1; i++) 23 f[i] = new int[v+1]; 24 if(needFull) //初始化细节详见 背包九讲1.4 25 { 26 for(int i = 0; i <= n; i++) 27 for(int j = 0; j <= v; j++) 28 f[i][j] = MIN; 29 f[0][0] = 0; 30 } 31 else 32 { 33 for(int i = 0; i <= n; i++) 34 for(int j = 0; j <= v; j++) 35 f[i][j] = 0; 36 } 37 38 for(int i = 1; i <= n; i++) 39 for(int j = c[i]; j <= v; j++) 40 { 41 f[i][j] = max(f[i - 1][j], f[i - 1][j - c[i]] + w[i]); 42 } 43 if(f[n][v] < 0)return -1; //针对背包装满的情况,没有满足的答案 44 return f[n][v]; 45 } 46 47 int ZeroOnePack2(int n, int v, int c[], int w[], bool needFull) 48 { 49 //根据tianyi cui背包九讲1.3在1.2的基础上优化空间复杂度后的解法 50 //时间复杂度均为O(nv),空间复杂度为O(v) 51 // n 物品数量 52 // v 背包容量 53 // c[] 物品耗费的空间,从c[1]开始 54 // w[] 物品的价值,从w[1]开始 55 // needFull 背包是否需要完全装满 56 const int MIN = numeric_limits<int>::min(); //表示负无穷 57 int *f = new int[v+1]; 58 if(needFull) //初始化细节详见 背包九讲1.4 59 { 60 for(int i = 0; i <= v; i++) 61 f[i] = MIN; 62 f[0] = 0; 63 } 64 else 65 { 66 for(int i = 0; i <= v; i++) 67 f[i] = 0; 68 } 69 70 for(int i = 1; i <= n; i++) 71 for(int j = v; j >= c[i]; j--) 72 { 73 f[j] = max(f[j], f[j - c[i]] + w[i]); 74 } 75 if(f[v] < 0)return -1; //针对背包装满的情况,没有满足的答案 76 return f[v]; 77 } 78 79 int ZeroOnePack3(int n, int v, int c[], int w[], bool needFull) 80 { 81 //根据tianyi cui背包九讲1.5,在1.3的基础上有个常数的优化,在v较大时,有明显优势 82 //时间复杂度均为O(nv),空间复杂度为O(v) 83 // n 物品数量 84 // v 背包容量 85 // c[] 物品耗费的空间,从c[1]开始 86 // w[] 物品的价值,从w[1]开始 87 // needFull 背包是否需要完全装满 88 const int MIN = numeric_limits<int>::min(); //表示负无穷 89 int *f = new int[v+1]; 90 if(needFull) //初始化细节详见 背包九讲1.4 91 { 92 for(int i = 0; i <= v; i++) 93 f[i] = MIN; 94 f[0] = 0; 95 } 96 else 97 { 98 for(int i = 0; i <= v; i++) 99 f[i] = 0; 100 } 101 102 int csum = 0; 103 c[0] = 0; 104 for(int i = 1; i <= n; i++)csum += c[i]; 105 for(int i = 1; i <= n; i++) 106 { 107 csum -= c[i-1]; 108 for(int j = v; j >= max(c[i], v - csum); j--) 109 { 110 f[j] = max(f[j], f[j - c[i]] + w[i]); 111 } 112 } 113 if(f[v] < 0)return -1; //针对背包装满的情况,没有满足的答案 114 return f[v]; 115 } 116 117 int main() 118 { 119 //87 120 int c[] = {0,2,7,3,4,8,5,8,6,4,16}; 121 int w[] = {0,15,25,8,9,15,9,13,9,6,14}; 122 int result = ZeroOnePack3(10, 34, c, w, true); 123 cout<< result <<endl; 124 125 //82 126 int c1[] = {0,4,5,7,2,8,3,6,1,10,9}; 127 int w1[] = {0,25,14,15,4,14,5,8,1,10,2}; 128 int result1 = ZeroOnePack3(10, 34, c1, w1, true); 129 cout<< result1 <<endl; 130 131 //-1 132 int c2[] = {0,2,3,6}; 133 int w2[] = {0,15,10,16}; 134 int result2 = ZeroOnePack3(3, 10, c2, w2, true); 135 cout<< result2 <<endl; 136 137 //85 138 int c3[] = {0,2,8,4,4,8,7,8,5,16,16}; 139 int w3[] = {0,15,25,9,9,15,12,12,6,14,9}; 140 int result3 = ZeroOnePack3(10, 34, c3, w3, true); 141 cout<< result3 <<endl; 142 143 //83 144 int c4[] = {0,4,5,7,2,8,3,9,6,1,10}; 145 int w4[] = {0,25,14,15,4,14,5,14,8,1,10}; 146 int result4 = ZeroOnePack3(10, 34, c4, w4, true); 147 cout<< result4 <<endl; 148 }
【版权声明】转载请注明出处 http://www.cnblogs.com/TenosDoIt/p/3139092.html