背包問題變形(動態規划),求一堆數字分成兩組,使得兩組和的差值最小。


 這個問題類似於背包問題,我們只要稍微改編一下就行。也就是相當於從一堆數字里面挑選一些數,然后使其接近總和的1/2。然然加入的每個數字的價值都看成1。下面附上python寫的源代碼,供大家參考。

import numpy as np
#n個物體的重量(w[0]無用)
w = np.array([0, 2, 5, 6, 9, 4, 5, 8, 5])
#n個物體的價值(p[0]無用)
p = [0, 1, 1, 1, 1, 1, 1, 1, 1]
#計算n的個數
n = len(w) - 1
#背包的載重量
m = int(np.ceil(0.5*np.sum(w)))
#裝入背包的物體,元素為True時,對應物體被裝入(x[0]無用)
x = [False for raw in range(n + 1)]
#optp[i][j]表示在前i個物體中,能夠裝入載重量為j的背包中的物體的最大價值
optp = [[0 for col in range(m + 1)] for raw in range(n + 1)]

def knapsack_dynamic(w, p, n, m, x):
#計算optp[i][j]
for i in range(1, n + 1):
for j in range(1, m + 1):
optp[i][j] = optp[i - 1][j]
if (j >= w[i]) and (optp[i - 1][j - w[i]] + p[i] > optp[i - 1][j]):
optp[i][j] = optp[i - 1][j - w[i]] + p[i]

#遞推裝入背包的物體
j = m
for i in range(n, 0, -1):
if optp[i][j] > optp[i - 1][j]:
x[i] = True
j = j - w[i]
knapsack_dynamic(w, p, n, m, x)
s1=np.sum(w[x])
s2=np.sum(w)-s1
difference=np.abs(s1-s2)
print('可供選擇的數字為:', w[1:])
print('第一組選擇的數字為:', w[x])
print('第一組的數字和為:', s1)
print('第二組的數字和為:', s2)
print('兩組數的和最小差異為:', difference)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM