01 前言
經過小編這幾天冒着掛科的風險,日日修煉,終於趕在考試周中又給大家更新了一篇干貨文章。關於用變鄰域搜索解決0-1背包問題的代碼。怎樣,大家有沒有很感動?
02 什么是0-1背包問題?
0-1 背包問題:給定 n 種物品和一個容量為 C 的背包,物品 i 的重量是** w_i,其價值為 v_i **。
問:應該如何選擇裝入背包的物品,使得裝入背包中的物品的總價值最大?
為什么叫0-1背包問題呢?顯然,面對每個物品,我們只有選擇拿取或者不拿兩種選擇,不能選擇裝入某物品的一部分,也不能裝入同一物品多次。拿就是1,不拿就是0。因此,就叫0-1背包問題。So simple, so naive.
03 代碼小講解
下面就幾個鄰域小動作給大家講解一下。
解決方案設計
假設我們面前有n種物品,那么我們可以將解決方案設置成一個一維數組selection[n]。數組weights[n]表示重量,數組values[n]表示價值。
-
selection[i] = 1 表示裝入第i個物品。
-
selection[i] = 0 表示不裝入第i個物品。
-
總價值total_value = selection[i] * values[i]。 (i=1,2,3,4……n)
-
總重量total_weight = selection[i] * weights[i]。(i=1,2,3,4……n)
鄰域動作1
將解決方案selection[n]的第i位取反(i=1,2,3,4……n)。比如:
有方案0010,那么生成的鄰居解則有1010(第一位取反)、0110(第二位取反)、0000(第三位取反)、0011(第四位取反)。
不知道這么通俗易懂的大家understand了沒有。
鄰域動作2
對於解決方案selection[n],在第i (i=1,2,3,4……n)位取反的情況下,依次將第j ** (j=i+1,2,3,4……n)位也取反**。還是for 一個 example吧。
對於解決方案0010。產生的鄰居解如下:
鄰域動作3
交換第i位和第i-3位的數。如果i<3。就交換最后的,比如:
-
selection[0]和selection[n-1]交換。
-
selection[1]和selection[n-2]交換。
-
selection[2]和selection[n-3]交換。
shaking程序
這個比較簡單,隨機取反一些位就行了。
下面上代碼啦!欲直接下載代碼文件,關注我們的公眾號哦!回復【VNSKP】即可,不包括【】哦