小孩分油问题的广度优先算法算法和深度优先算法的python代码实现

小孩分油问题:

两个小孩去打油,一人带了一个一斤的空瓶,另一个带了一个七两、一个三两的空瓶。原计划各打一斤油,可是由于所带的钱不够,只好两人合打了一斤油,在回家的路上,两人想平分这一斤油,可是又没有其它工具。试仅用三个瓶子(一斤、七两、三两)精确地分出两个半斤油来。

说明:

一斤 = 10两;

算法设计:
设置三个油瓶分别为A, B, C,初始化三个油瓶的初始状态(10,0,0),满油状态(10,7,3),目标状态(5,5,0)。使用广度优先的搜索方法,对每一种可能情况进行遍历,最终取得结果。其中,对于每一种情况对应每一步操作,操作需要满足一定的约束条件:把A瓶中的油全部倒入B瓶或者把A瓶中的油部分倒入B瓶使B瓶满油。

广度搜索 (BFS)代码实现:

from collections import deque


def nextStep(current_state, oil_volume):
    next_actions = [
        (from_, to_)
        for from_ in range(3) for to_ in range(3)
        if from_ != to_ and current_state[from_] > 0 and current_state[to_] < oil_volume[to_]
    ]

    for from_, to_ in next_actions:
        next_state = list(current_state)
        transfer_amount = min(current_state[from_], oil_volume[to_] - current_state[to_])
        next_state[from_] -= transfer_amount
        next_state[to_] += transfer_amount
        yield next_state

def depthFirstSearch(record, oil_volume=[10, 7, 3], final_state=[5, 5, 0]):
    global num, record_list
    current_state = record[-1]
    
    if current_state == final_state:
        num += 1
        record_list.append(deque(record))
        print(f"方法{num}: {'->'.join(map(str, record))}")
        return

    next_stages = nextStep(current_state, oil_volume)
    for stage in next_stages:
        if stage not in record:
            record.append(stage)
            depthFirstSearch(record, oil_volume, final_state)
            record.pop()

if __name__ == '__main__':
    initial_oil_state = [10, 0, 0]
    num = 0
    record_list = []
    record = deque()
    record.append(initial_oil_state)
    depthFirstSearch(record)
    number = f"深度优先搜索共有{num}种方法"
    shortest = f"路径最短的方法中操作步总数为{min(len(i) for i in record_list)}"

    print(number)
    print(shortest)


from collections import deque

def nextStep(current_state, oil_volume):
    next_actions = [
        (from_, to_)
        for from_ in range(3) for to_ in range(3)
        if from_ != to_ and current_state[from_] > 0 and current_state[to_] < oil_volume[to_]
    ]

    for from_, to_ in next_actions:
        next_state = list(current_state)
        transfer_amount = min(current_state[from_], oil_volume[to_] - current_state[to_])
        next_state[from_] -= transfer_amount
        next_state[to_] += transfer_amount
        yield next_state

def searchResult(record, oil_volume=[10, 7, 3], final_state=[5, 5, 0]):
    global num, record_list
    current_state = record[-1]
    next_stages = nextStep(current_state, oil_volume)

    for stage in next_stages:
        if stage not in record:
            record.append(stage)
            if stage == final_state:
                num += 1
                record_list.append(deque(record))
                print(f"方法{num}: {'->'.join(map(str, record))}")
            else:
                searchResult(record, oil_volume, final_state)
            record.pop()

if __name__ == '__main__':
    initial_oil_state = [10, 0, 0]
    num = 0
    record_list = []
    record = deque()
    record.append(initial_oil_state)
    searchResult(record)
    number = f"广度优先搜索共有{num}种方法"
    shortest = f"路径最短的方法中操作步总数为{min(len(i) for i in record_list)}"

    print(number)
    print(shortest)

代码结果

222

结论:
由代码运行结果可知:整棵树一共有20种方法能够达到要求,其中最佳即路径最短的方法为第9种方法。
第9种方法:[10, 0, 0]->[3, 7, 0]->[3, 4, 3]->[6, 4, 0]->[6, 1, 3]->[9, 1, 0]->[9, 0, 1]->[2, 7, 1]->[2, 5, 3]->[5, 5, 0]
具体做法为:
0) 初始化–>[10, 0, 0]

  1. A瓶倒满B瓶–>[3, 7, 0]
  2. B瓶倒满C瓶–>[3, 4, 3]
  3. C瓶倒满A瓶–>[6, 4, 0]
  4. B瓶倒满C瓶–>[6, 1, 3]
  5. C瓶倒满A瓶–>[9, 1, 0]
  6. B瓶倒满C瓶–>[9, 0, 1]
  7. A瓶倒满B瓶–>[2, 7, 1]
  8. B瓶倒满C瓶–>[2, 5, 3]
  9. C瓶倒满A瓶–>[5, 5, 0]

深度优先搜索 (DFS):从起始节点出发,尽可能深入到图的最深层,然后再回溯,继续深入到下一个分支。它使用堆栈(递归或显式堆栈)来维护节点的访问顺序。广度优先搜索 (BFS):从起始节点开始,首先访问其所有的相邻节点,然后逐层地向外扩展,直到找到目标节点或遍历完整个图。它使用队列来维护节点的访问顺序。遍历顺序:DFS 通常倾向于深度遍历,即沿着一条路径尽可能深入,然后回溯到上一个分支。这可能导致较长的路径被首先探索。BFS 倾向于逐层遍历,首先探索距离起始节点最近的节点,然后逐渐向外扩展。这通常导致找到的路径较短。数据结构:DFS 使用堆栈(递归或显式堆栈)来维护节点的访问顺序。BFS 使用队列来维护节点的访问顺序。相似之处:应用领域:DFS和BFS都可以用于解决各种问题,包括图遍历、路径查找、状态空间搜索、拓扑排序等。完备性:如果问题有解,DFS和BFS都能找到解,但不一定是最优解。DFS可能找到的不是最短路径,而BFS通常能找到最短路径。时间复杂度:在最坏情况下,DFS和BFS的时间复杂度都可以达到O(V + E),其中V是节点数,E是边数。但在实际应用中,它们的性能可能会有所不同,取决于问题的性质和图的结构。空间复杂度:DFS通常需要较少的空间,因为它只需要维护一个栈,而BFS需要维护一个队列,可能需要更多的内存空间。总之,DFS和BFS是两种不同的搜索策略,各自适用于不同的问题和场景。DFS适用于深度搜索,通常用于找到解的问题。BFS适用于广度搜索,通常用于找到最短路径或最短步数的问题。选择哪种算法取决于具体问题的需求和图的结构。

  • 19
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值