回溯 皇后 算法笔记_算法笔记-回溯法
(1)0-1背包問題
思路:構造一個二叉樹,每個商品都有兩種狀態,要或者不要。如果要就在這個節點的左枝掛子節點,如果不要就在右節點掛子節點。如果全部商品都分配完狀態之后就回溯,回溯到一個還有其他選擇的節點,接著往這個選擇發展節點,然后再回溯,然后再往下。。。。? 直到無路可走,就結束了。
假如限制重量是10,總共有四個商品,重量分別是2, 5, 4, 2 價格分別是6, 3, 5, 4。第一輪的路程如5-11圖,第1個商品要,第2個商品要,第3個商品發現裝不下了,所以到第3個節點只能走右節點,并且第3個節點的左節點成為死節點,沒有發展下去的可能了。第4個商品要,此時已經給所有的商品賦予狀態了(要或者不要),記錄下此時所有商品的價值和,記為最優價格。接著就開始回溯,如5-13,從節點5先是回溯到節點4(此時購物車有1,2,3選擇不要,4肯定是要的,所以沒必要再發展4節點的右節點),再到節點3(節點三的左節點是死節點),再到節點2,節點2的右節點是可選的,然后接著按照剛開始的邏輯接著往下走就可以了,等繼續走完這一輪,計算最優值,更新下最優值,然后再回溯。。。
剪枝:如果按照上面的邏輯,其實幾乎相當于遍歷了所有的可能性。如果有4個商品,就會有2的4次方種可能,有些不可能是最優結果的分支直接就剪掉就可以了,比如,如果按照上面的邏輯是會有:1不要2不要3不要4不要這個分支。所以如果發現背包可以把剩下的商品都裝入的情況,就直接給剩余的商品賦值為要就可以了。當1不要2不要的時候,3和4可以都裝入背包,直接都要就可以了。沒必要再走3不要的分支(直接設置成死節點)。或者也可以判斷就算把剩余的都加進包里,總價值也小于當前最優值,當前這條路也沒必要走了。
代碼:
1 <?php2 $w = [2, 5, 4, 2];3 $v = [6, 3, 5, 4];4 $current = getNode(0);5 $count = count($w);6 list($limit, $best, $cw, $cp, $bestMap, $map) = [10, 0, 0, 0, array(), array()];7 $noBack = true;8
9 while (1) {10 $node = getNode($current->level + 1, $current);11 if ($current->level < $count && $noBack) {12 if ($best >= array_sum(array_slice($v, $current->level)) + $cp) {13 $current->l = false; //剪枝
14 $current->r = false;15 $noBack = false;16 } elseif (is_object($current->l)|| $current->l === false) {17 $node->dir = 0; //這種情況是回溯回來的,直接發展右節點就可以了
18 $current->r = & $node;19 } elseif ($cw + $w[$current->level] <= $limit) {20 $cw += $w[$current->level]; $cp += $v[$current->level];21 $node->dir = 1; //1代表左枝,0代表右枝
22 $current->l = & $node; //這種情況代表背包可以裝下,所以掛在左節點
23 $map[$current->level] = 1;24 } else{25 $node->dir = 0;26 $current->r = & $node;27 $current->l = false; //這種情況代表裝不下,左節點是死節點,發展右節點
28 }29 $current = & $node;30 } else { //走完一輪,開始回溯
31 if ($cp > $best) { //記錄最優值
32 $best = $cp; $bestMap = $map;33 }34 while (1) { //開始回溯
35 $deal = isset($current->dir) ? $current->dir : 0;36 $current = & $current->p;37 if ($current === null) {38 break 2; //到頭了,結束
39 }40 if (isset($map[$current->level])) {41 unset($map[$current->level]);42 $cw -= $w[$current->level] * $deal; //怎么加的,怎么減回去
43 $cp -= $v[$current->level] * $deal;44 }45 if ($current->l === null || $current->r === null) { //存在活結點
46 $noBack = true;47 break;48 }49 }50 }51 unset($node);52 }53
54 function getNode($level, & $p = null) {55 $node = newstdClass();56 $node->level = $level; $node->p = & $p;57 $node->l = null; $node->r = null;58 return $node;59 }60
61 print_r([‘map‘ => $bestMap, ‘val‘ => $best]);
原文:https://www.cnblogs.com/wangjianheng/p/11857435.html
總結
以上是生活随笔為你收集整理的回溯 皇后 算法笔记_算法笔记-回溯法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 即将放弃python的app_pytho
- 下一篇: 超全的英语短句汇集