|
23 | 23 | 其中<img src="http://latex.codecogs.com/gif.latex?V(W)" title="V(W)" />表示背包已装物品重量为M时的最大价值,上述比较的两者,前者表示不装第i件物品时,背包已经承载物品的最大价值,后者表示装了第i件物品后,剩余的空间可以装载物品的最大价值与第i件物品价值的和。两者取最大,则可保证最后的方案是最优的。
|
24 | 24 |
|
25 | 25 | 解题思路图示:
|
26 |
| - [!image](https://github.com/Anfany/Algorithm-Example-by-Python3/blob/master/0-1pack.png) |
| 26 | +  |
27 | 27 |
|
28 | 28 | 基于Python3的代码
|
29 | 29 | ```
|
@@ -73,7 +73,114 @@ print(ZeroOnePack_Simple(weight, value, maxweight))
|
73 | 73 | * **完全背包**
|
74 | 74 |
|
75 | 75 | + 有N件物品,背包的最大承重为M,**每件物品的数量无限**,价值集合为V,重量集合为W,计算该背包可以承载的物品的最大价值。
|
| 76 | + |
| 77 | + 这个和0-1背包的最大区别在于:每计算一次V值,就立即更新。其状态转移方程和0-1背包相同,因为有实时的更新V值,就相当于同一个物品可以多次选取。 |
| 78 | + |
| 79 | +下面给出基于Python3的代码 |
| 80 | +``` |
| 81 | +weight = [4, 3, 2, 6, 5] |
| 82 | +value = [3, 4, 6, 7, 9] |
| 83 | +maxweight = 8 |
| 84 | +
|
| 85 | +# 只输出最大价值 |
| 86 | +def CompletePack_Simple(W, V, MW):#完全背包 |
| 87 | + #存储最大价值的一维数组 |
| 88 | + valuelist = [0] * (MW + 1) |
| 89 | + #开始计算 |
| 90 | + for ii in range(len(W)):#从第一个物品 |
| 91 | + for jj in range(MW + 1):#从重量0 |
| 92 | + if jj >= W[ii]:#如果重量大于物品重量 |
| 93 | + valuelist[jj] = max(valuelist[jj - W[ii]] + V[ii], valuelist[jj])#选中第ii个物品和不选中,取大的 |
| 94 | + return '最大价值:', valuelist[-1] |
| 95 | +
|
| 96 | +# 也输出选择物品的编号以及个数 |
| 97 | +def CompletePack(W, V, MW):#完全背包 |
| 98 | + #存储最大价值的一维数组 |
| 99 | + valuelist = [0] * (MW + 1) |
| 100 | + #存储物品编号的字典 |
| 101 | + codedict = {i: [] for i in range(0, MW + 1)} |
| 102 | + #开始计算 |
| 103 | + for ii in range(len(W)):#从第一个物品 |
| 104 | + copyvalue = valuelist.copy() |
| 105 | + copydict = codedict.copy() |
| 106 | + for jj in range(MW + 1):#从重量0 |
| 107 | + if jj >= W[ii]:#如果重量大于物品重量 |
| 108 | + cc = copyvalue[jj] |
| 109 | + copyvalue[jj] = max(copyvalue[jj - W[ii]] + V[ii], copyvalue[jj])#选中第ii个物品和不选中,取大的 |
| 110 | + #输出被选中的物品编号 |
| 111 | + if copyvalue[jj] > cc: |
| 112 | + copydict[jj] = [ii] |
| 113 | + for hh in copydict[jj - W[ii]]: |
| 114 | + copydict[jj].append(hh) |
| 115 | + codedict = copydict.copy()#更新 |
| 116 | + valuelist = copyvalue.copy()#更新 |
| 117 | + result = '' |
| 118 | + for hcode in sorted(list(set(copydict[MW]))): |
| 119 | + result += '物品:%d :%d个' % (hcode + 1, copydict[MW].count(hcode)) |
| 120 | + print(result) |
| 121 | + return '最大价值:', valuelist[-1] |
| 122 | +
|
| 123 | +print(CompletePack_Simple(weight, value, maxweight)) |
| 124 | +``` |
76 | 125 |
|
77 | 126 | * **多重背包**
|
78 | 127 |
|
79 | 128 | + 有N件物品,背包的最大承重为M,**每件物品的数量集合为C**,价值集合为V,重量集合为W,计算该背包可以承载的物品的最大价值。
|
| 129 | + 这个和完全背包的最大区别在于:完全背包因为没有物品数量的限制,因此可以无限叠加。因此需要加上对数量的限制语句。 |
| 130 | + |
| 131 | +下面是基于Python3的代码 |
| 132 | +``` |
| 133 | +weight = [4, 3, 2, 6, 5] |
| 134 | +value = [3, 4, 6, 7, 9] |
| 135 | +count = [3, 2, 1, 1, 0] |
| 136 | +maxweight = 8 |
| 137 | +
|
| 138 | +# 只输出最大价值 |
| 139 | +def MultiplePack_Simple(W, V, C, MW): # 多重背包 |
| 140 | + # 存储最大价值的一维数组 |
| 141 | + valuelist = [0] * (MW + 1) |
| 142 | + # 开始计算 |
| 143 | + for ii in range(len(W)): # 从第一个物品 |
| 144 | + copyvalue = valuelist.copy() |
| 145 | + for jj in range(MW + 1): # 从重量0 |
| 146 | + if jj >= W[ii]: # 如果重量大于物品重量 |
| 147 | + for gg in range(C[ii] + 1): # 限制=数量 |
| 148 | + if gg * W[ii] <= jj: |
| 149 | + copyvalue[jj] = max(valuelist[jj - gg * W[ii]] + gg * V[ii], copyvalue[jj]) |
| 150 | + valuelist = copyvalue.copy() # 更新 |
| 151 | + return '最大价值:', valuelist[-1] |
| 152 | +
|
| 153 | +# 也输出编号以及个数 |
| 154 | +def MultiplePack(W, V, C, MW): # 多重背包 |
| 155 | + # 存储最大价值的一维数组 |
| 156 | + valuelist = [0] * (MW + 1) |
| 157 | + # 存储物品编号的字典 |
| 158 | + codedict = {i: [] for i in range(0, MW + 1)} |
| 159 | + # 开始计算 |
| 160 | + for ii in range(len(W)): # 从第一个物品 |
| 161 | + copyvalue = valuelist.copy() |
| 162 | + copydict = codedict.copy() |
| 163 | + # 存储物品所用数量的一维数组 |
| 164 | + number = [0] * (MW + 1) |
| 165 | + for jj in range(MW + 1): # 从重量0 |
| 166 | + if jj >= W[ii]: # 如果重量大于物品重量 |
| 167 | + for gg in range(C[ii] + 1): # 限制数量 |
| 168 | + cc = copyvalue[jj] |
| 169 | + if gg * W[ii] <= jj: |
| 170 | + copyvalue[jj] = max(valuelist[jj - gg * W[ii]] + gg * V[ii], copyvalue[jj]) |
| 171 | + if copyvalue[jj] > cc: |
| 172 | + number[jj] += 1 |
| 173 | + copydict[jj] = number[jj] * [ii] |
| 174 | + for hh in codedict[jj - number[jj] * W[ii]]: |
| 175 | + copydict[jj].append(hh) |
| 176 | + codedict = copydict.copy() # 更新 |
| 177 | + valuelist = copyvalue.copy() # 更新 |
| 178 | + result = '' |
| 179 | + for hcode in sorted(list(set(copydict[MW]))): |
| 180 | + result += '物品:%d: %d个。' % (hcode + 1, copydict[MW].count(hcode)) |
| 181 | + print(result) |
| 182 | + return '最大价值:', valuelist[-1] |
| 183 | +
|
| 184 | +
|
| 185 | +print(MultiplePack_Simple(weight, value, count, maxweight)) |
| 186 | +``` |
0 commit comments