【问题描述】使用动态规划算法解0-1背包问题,具体来说就是,依据递归式,按照顺序求得子问题,使得选择合适物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大。
【输入形式】在屏幕上输入背包容量、物品数量、每件物品价值和重量。
【输出形式】最优解时所选物品编号。
【样例输入】
10
5
6 3 5 4 6
2 2 6 5 4
【样例输出】
1 2 5
【样例说明】
输入:背包容量10、物品数量5、每件物品价值6, 3, 5, 4, 6和重量2, 2, 6, 5, 4。
输出:最优解时选择物品编号为1,2,5。
【评分标准】根据输入得到准确的输出。
import numpy as np
def knapsack(v, w, c, n, m):
jm = min(w[n-1]-1, c)
for j in range(0, jm+1):
m[n, j] = 0
for j in range(w[n-1], c+1):
m[n, j] = v[n-1]
for i in range(n-1, 1, -1):
jm = min(w[i-1]-1, c)
for j in range(0, jm+1):
m[i, j] = m[i+1, j]
for j in range(w[i-1], c):
m[i, j] = max(m[i+1, j], m[i+1, j-w[i-1]]+v[i-1])
m[1, c] = m[2, c]
if c >= w[0]:
m[1, c] = max(m[1, c], m[2, c-w[0]]+v[0])
def traceback(m, w, c, n, x):
for i in range(1, n):
if m[i, c] == m[i+1, c]:
x[i] = 0
else:
x[i] = 1
c -= w[i-1]
if m[n, c] > 0:
x[n] = 1
else:
x[n] = 0
def main():
c = int(input())
n = int(input())
v = np.array(list(map(int, input().split())))
w = np.array(list(map(int, input().split())))
m = np.zeros((n+1, c+1), dtype=int)
x = np.zeros(n+1, dtype=int)
knapsack(v, w, c, n, m)
traceback(m, w, c, n, x)
# print(v)
# print(m[1, c])
for i in range(1, n+1):
if x[i] == 1:
print(i, end=' ')
if __name__ == "__main__":
main()
更好理解的写法(张张讲的):
import numpy as np
def packagedp(c, n, v, w):
m = np.zeros((n+2, c+1), dtype=np.int)
x = np.zeros((n+1), dtype=np.int)
for i in range(n, 0, -1):
for j in range(0, c+1):
m[i, j] = m[i+1, j]
if j >= w[i-1]:
m[i, j] = max(m[i, j], m[i+1, j-w[i-1]]+v[i-1])
for i in range(1, n):
if w[i, c] == w[i+1, c]:
x[i] = 0
else:
x[i] = 1
c = c-w[i-1]
if m[n, c] > 0:
x[n] = 1
else:
x[n] = 0
return x, m
def main():
c = int(input())
n = int(input())
v = np.array(list(int(i) for i in input().split()))
w = np.array(list(int(i) for i in input().split()))
x, m = packagedp(c, n, v, w)
# print(m)
for i in range(1, n+1):
if x[i] == 1:
print(i, end='')
if __name__ == '__main__':
main()