解決過程
- 黃色是我計算錯誤的單元格
- 大體的過程是每次都要考慮當前容量,當前物品的價值是否超過上一個物品,如果沒有,照抄。如果有,揹包沒有滿,那麼找到上一行,剩餘容量那個單元格,將其價值和當前物品價值相加。
源代碼
# n:物品件數;
# c:最大承重爲c的揹包;
# w:各個物品的重量;
# v:各個物品的價值;
# res[i][j]是(n+1)(c+1)的矩陣,取值從[1][1]開始, 而n[i],c[i],p[i],w[i]都是從0開始取值
def bag(n, c, w, p):
res = [[-1 for j in range(c + 1)] for i in range(n + 1)] # 生成(n+1)(c+1)的矩陣
for j in range(c + 1):
# 第0行全部賦值爲0,物品編號從1開始.方便賦值
res[0][j] = 0
# print(res)
for i in range(1,n + 1): # 遍歷物品列
for j in range(1,c + 1): # 遍歷容量列 標記💕
res[i][j] = res[i - 1][j] # 相同位置的上一行
# j >= w[i - 1]先查看當前揹包容量是否大於上一行物品(×),但爲什麼檢查的是上一列的物品,因爲要查看是否能加入上一列物品
# w[i-1]就是代表第n行物品
# res[i - 1][j - w[i - 1]] + p[i - 1]用來計算加入當前物品後,剩餘容量能否再加入物品,加入後是否超過當前價值
if (j >= w[i - 1]) and res[i - 1][j - w[i - 1]] + p[i - 1] > res[i][j]:
res[i][j] = res[i - 1][j - w[i - 1]] + p[i - 1]
return res
# 在相同價值情況下,後一件物品比前一件物品的最大價值大,則表示物品i有被加入到揹包
def show(n, c, w, res):
print('最大價值爲:', res[n][c]) # 最大的價值在矩陣的最後一個元素
# 展示選擇物品方案1
# j=c
# print('選擇的物品爲:')
# for i in range(1,len(res)):
# # 遍歷res每i行,第j列元素
# if res[i][j]>res[i-1][j]:
# print('第', i, '個',end=' ')
# j-=w[i-1] # 重點
# 展示選擇物品方案2
x = [False for i in range(n)] # 默認所有物品沒有選擇
j = c # j保存最大容量
for i in range(1, n + 1):
if res[i][j] > res[i - 1][j]:
x[i - 1] = True #res數組和x數組相差1個位置
j -= w[i - 1]
print('選擇的物品爲:')
for i in range(n):
if x[i]:
print('第', i+1, '個',end=' ')
if __name__ == '__main__':
n = 5
c = 10
w = [2, 2, 6, 5, 4]
p = [6, 3, 5, 4, 6]
res = bag(n, c, w, p)
print(res)
show(n, c, w, res)
res打印
Q&A
- 第一行數據有啥用?第一列數據能否取消?
- 答:第一行如果沒有,第二行應該如何做價值比較?
第一列:我嘗試了將第一列去掉,發現有趣的事情,假設沒有第一列,那麼所有元素都要向左移動一個單元,也就是說,💕這一行代碼的計數器應該從0開始,此時j也代表着容量,那麼勢必會影響最後的結果,還是會多出一列無用的,少了一列有用的
-
每一行中的單元格在計算價值時候,只能選擇當前行的以上的的物品
-
剩下容量該如何分配
-答:找到上一行,第(總容量➖當前物品容量)列的價值