深度优先遍历算法-01小偷偷东西问题
生活随笔
收集整理的這篇文章主要介紹了
深度优先遍历算法-01小偷偷东西问题
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
小偷偷東西問題
- 前言
- 深度優(yōu)先遍歷是經(jīng)典的圖論算法,深度優(yōu)先遍歷算法的搜索邏輯和它的名字一樣,只要有可能,就盡量深入搜索,直到找到答案,或者嘗試了所有可能后確定沒有解。
- 簡單來說,深度優(yōu)先遍歷就是按照某規(guī)則(如檢索當(dāng)前節(jié)點(diǎn)的第一個(gè)子節(jié)點(diǎn))檢索某個(gè)節(jié)點(diǎn),直到檢索完畢再去檢索其他節(jié)點(diǎn)。
- 搜索問題的本質(zhì)就是試探問題的所有可能選擇,按照特定的規(guī)律和順序,不斷去搜索答案,直到找到問題的解。如果把所有可能都走了一遍,還沒有找到解,就說明這個(gè)問題沒有解。注意:深度優(yōu)先遍歷一定要按照規(guī)則嘗試所有的可能。
- 深度優(yōu)先遍歷是圖論的經(jīng)典算法,從某個(gè)節(jié)點(diǎn)v出發(fā)開始進(jìn)行搜索,不斷搜索直到該節(jié)點(diǎn)的所有邊都被遍歷完。當(dāng)節(jié)點(diǎn)v的所有邊都被遍歷以后,深度優(yōu)先遍歷算法則需要回溯到v的前驅(qū)節(jié)點(diǎn),來繼續(xù)搜索這個(gè)前驅(qū)節(jié)點(diǎn)的其他邊。如果還存在尚未被遍歷的節(jié)點(diǎn),則深度優(yōu)先遍歷算法會(huì)按照統(tǒng)一的規(guī)則從這些剩下的節(jié)點(diǎn)中選擇一個(gè)節(jié)點(diǎn)再重復(fù)同樣的遍歷過程。這樣的搜索過程從最開始的節(jié)點(diǎn)一直持續(xù)到最后一個(gè)節(jié)點(diǎn)的所有邊都遍歷完。
- 二叉樹的先序、后序和中序都屬于深度優(yōu)先遍歷,層序遍歷屬于廣度優(yōu)先遍歷。(關(guān)于二叉樹的數(shù)據(jù)結(jié)構(gòu)只是不提)
- 問題描述
- 有一個(gè)小區(qū)的別墅按照二叉樹結(jié)構(gòu)分布,也就是說,除了第一個(gè)別墅,其余每個(gè)別墅都和另一個(gè)“父”別墅連接?,F(xiàn)在有個(gè)小偷,想要進(jìn)入別墅偷竊,但是,一旦進(jìn)入兩個(gè)直接連接的別墅(只會(huì)有一段線相連),警報(bào)會(huì)觸發(fā),每個(gè)節(jié)點(diǎn)的值表示別墅財(cái)務(wù)的價(jià)值,問如何走在不報(bào)警的情況下偷得最多財(cái)物。
- 問題分析
- 對于上圖,顯然我選擇頭4和5這兩個(gè)別墅,得到最多財(cái)物。
- 顯然,一旦選擇了某個(gè)節(jié)點(diǎn),就意味著放棄所有的這個(gè)節(jié)點(diǎn)的直接子節(jié)點(diǎn)(在下一層與之相連的節(jié)點(diǎn))。
- 不妨定義節(jié)點(diǎn)這個(gè)數(shù)據(jù)結(jié)構(gòu)記錄當(dāng)前節(jié)點(diǎn)的價(jià)值,以及偷了該節(jié)點(diǎn)得到的價(jià)值和不偷該節(jié)點(diǎn)得到的價(jià)值。很容易發(fā)現(xiàn),每個(gè)節(jié)點(diǎn)的偷值是左側(cè)子節(jié)點(diǎn)的不偷值+右側(cè)子節(jié)點(diǎn)的不偷值+節(jié)點(diǎn)的價(jià)值,每個(gè)節(jié)點(diǎn)的不偷值是左側(cè)子節(jié)點(diǎn)的最大值(偷與不偷中較大者)+右側(cè)子節(jié)點(diǎn)的最大值。
- 那么想要得到根節(jié)點(diǎn)的偷與不偷值,只要知道其子節(jié)點(diǎn)的,其子節(jié)點(diǎn)的又是來自子節(jié)點(diǎn)的子節(jié)點(diǎn)的,顯然,這是一個(gè)遞歸過程,最底層節(jié)點(diǎn)的屬性值一開始是確定的,用來構(gòu)造父節(jié)點(diǎn)的屬性值。最后輸出根節(jié)點(diǎn)的兩值較大者即可。
- 代碼
- # -*-coding:utf-8-*-class TreeNode:def __init__(self, x, l, r):self.value = xself.left = lself.right = rdef get_value(root):rst = search(root)return max(rst[0], rst[1])def search(root):"""返回二維數(shù)組[偷值,不偷值]:param root::return:"""if root is None:return [0, 0]left = search(root.left)right = search(root.right)rob_value = root.value + left[1] + right[1]skip_value = max(left[0], left[1]) + max(right[0], right[1])return rob_value, skip_valueif __name__ == '__main__':f = TreeNode(1, None, None)e = TreeNode(3, None, None)d = TreeNode(1, None, None)b = TreeNode(4, d, e)c = TreeNode(5, f, None)a = TreeNode(3, b, c)print(get_value(a))
- 補(bǔ)充說明
- 具體代碼可以查看我的Github,歡迎Star或者Fork
- 參考書《你也能看得懂的Python算法書》
- 顯然,這種思路適合求得最優(yōu)解,但是對于輸出具體路徑略顯麻煩。
總結(jié)
以上是生活随笔為你收集整理的深度优先遍历算法-01小偷偷东西问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Markdown-基础语法
- 下一篇: 深度优先遍历算法-03二叉树路径遍历问题