void backtrack(int t){if(t > n) output(x);else{for(int i = f(n,t); i <= g(n,t);i++){
x[t]= h(i);if(constraint(t)&& bound(t)) backtrack(t+1);}}}
递归实现:分成3个部分,为了使用限界函数,需要把数据降序排序,限界函数,以及回溯函数。
defpack_01_back_prune(N,V,C,W):
BestResult =[False]*N
Selected =[False]*(N)
BestValue =[0]
CurCost =[0]
CurValue =[0]
order =[i for i inrange(N)]
perp =[0]*N
# sorted by value per weightdefsort_group(C,W,O):
perp =[0]*N
for i inrange(N):
perp[i]= W[i]/C[i]for i inrange(N-1):for j inrange(i+1,N):if perp[i]< perp[j]:
temp = perp[i]
perp[i]= perp[j]
perp[j]= temp
temp = O[i]
O[i]= O[j]
O[j]= temp
temp = C[i]
C[i]= C[j]
C[j]= temp
temp = W[i]
W[i]= W[j]
W[j]= temp
return perp,C,W,O
# 计算上界函数,功能为剪枝# 判断当前背包的总价值cp+剩余容量可容纳的最大价值<=当前最优价值defbound(depth):
left_weight = V - CurCost[0]
b = CurValue[0]while depth < N and C[depth]<= left_weight:
left_weight -=C[depth]
b += W[depth]
depth +=1if depth < N:
b += perp[depth]* left_weight
return b
defbacktracking(depth):if depth > N-1:if CurValue[0]> BestValue[0]:
BestValue[0]= CurValue[0]
BestResult[:]= Selected[:]else:# 如若左子节点可行,则直接搜索左子树;# 对于右子树,先计算上界函数,以判断是否将其减去if CurCost[0]+ C[depth]<= V :# and bound(depth+1) > BestValue[0]:
Selected[depth]=True
CurCost[0]+= C[depth]
CurValue[0]+= W[depth]# next
backtracking(depth+1)# undo
CurCost[0]-= C[depth]
CurValue[0]-= W[depth]# 如若符合条件则搜索右子树 if bound(depth+1)> BestValue[0]:
Selected[depth]=False
backtracking(depth+1)
perp,C,W,order = sort_group(C,W,order)
backtracking(0)# 把结果恢复成原来顺序
decode_BestResult =[False]*N
for i inrange(N):if BestResult[i]:
decode_BestResult[order[i]]=Truereturn decode_BestResult,BestValue
迭代方式,顺序执行,注意一点,就是不满足限界函数时,需要提前进入回溯
#%%defpack_01_back_prune_iteration(N,V,C,W):
BestResult =[False]*N
Selected =[False]*(N)
BestValue =[0]
CurCost =[0]
CurValue =[0]
order =[i for i inrange(N)]
perp =[0]*N
# sorted by value per weightdefsort_group(C,W,O):
perp =[0]*N
for i inrange(N):
perp[i]= W[i]/C[i]for i inrange(N-1):for j inrange(i+1,N):if perp[i]< perp[j]:
temp = perp[i]
perp[i]= perp[j]
perp[j]= temp
temp = O[i]
O[i]= O[j]
O[j]= temp
temp = C[i]
C[i]= C[j]
C[j]= temp
temp = W[i]
W[i]= W[j]
W[j]= temp
return perp,C,W,O
# 计算上界函数,功能为剪枝# 判断当前背包的总价值cp+剩余容量可容纳的最大价值<=当前最优价值defbound(depth):
left_weight = V - CurCost[0]
b = CurValue[0]while depth < N and C[depth]<= left_weight:
left_weight -=C[depth]
b += W[depth]
depth +=1if depth < N:
b += perp[depth]* left_weight
return b
defbacktracking_iteration(depth):whileTrue:if depth < N:# 进入1的分支if CurCost[0]+ C[depth]<= V and bound(depth+1)> BestValue[0]:
Selected[depth]=True
CurCost[0]+= C[depth]
CurValue[0]+= W[depth]# 进入0的分支elif bound(depth+1)> BestValue[0]:
Selected[depth]=False# 不满足限界函数,回溯 else:while depth >=0andnot Selected[depth]:
depth -=1if depth <0:breakelse:
Selected[depth]=False
CurCost[0]-= C[depth]
CurValue[0]-= W[depth]else:if CurValue[0]> BestValue[0]:
BestValue[0]= CurValue[0]
BestResult[:]= Selected[:]# 到底部回溯,这时候,depth已经穿了
depth -=1while depth >=0andnot Selected[depth]:
depth -=1if depth <0:breakelse:
Selected[depth]=False
CurCost[0]-= C[depth]
CurValue[0]-= W[depth]
depth +=1
perp,C,W,order = sort_group(C,W,order)
backtracking_iteration(0)
decode_BestResult =[False]*N
for i inrange(N):if BestResult[i]:
decode_BestResult[order[i]]=Truereturn decode_BestResult,BestValue
输出结果
#%%
N =8
V =30
C =[11,2,3,9,13,6,15,7,19]
W =[5.0,2.0,5.0,7.0,5.0,11.0,6.0,14.0]#print pack_01_back(N,V,C,W)#print pack_01_back_iteration(N,V,C,W)#print pack_01_back_iteration2(N,V,C,W)print pack_01_back_prune(N,V,C,W)print pack_01_back_prune_iteration(N,V,C,W)
runfile('/root/test/back_tracking.py', wdir='/root/test')([False,True,True,True,False,True,False,True],[39.0])
runfile('/root/test/back_tracking.py', wdir='/root/test')([False,True,True,True,False,True,False,True],[39.0])