油瓶分油问题 python实现

一、问题描述

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

二、解题思路

选择合适的数据结构表示问题状态:
用向量(A, B, C)表示状态——其中A表示10斤油瓶的油量,B表示7斤油瓶中的油量,C表示3斤油瓶中的油量。
问题的初始状态:(10, 0, 0)
问题的目标状态:(5, 5, 0)

确定智能算子,即状态变化的规则:

规则号 规则 解释
1 (A, B, C) and B < 7 -> (3-C, 7, C) 7两瓶不满时用10两瓶装满
2 (A, B, C) and C < 3 -> (7-B, B, 3) 3两瓶不满时用10两瓶装满
3 (A, B, C) and B > 0 -> (10-C ,0, C) 7两瓶不空时,倒空至10两瓶
4 (A, B, C) and C > 0 -> (10-B, B, 0) 3两瓶不空时,倒空至10两瓶
5 (A, B, C) and B > 0 and B + C <= 3 -> (A, 0, B+C) 7两瓶中的油全部倒入3两瓶中
6 (A, B, C) and C > 0 and B + C <= 7 -> (A, B+C, 0) 3两瓶中的油全部倒入7两瓶中
7 (A, B, C) and B < 7 and B + C >= 7 -> (A, 7, B+C-7) 用3两瓶中的油装满7两瓶
8 (A, B, C) and C < 3 and B + C >= 3 -> (A, B+C-3, 3) 用7两瓶中的油装满3两瓶

三、方法实现

数据结构与算法:

使用广度优先搜索对状态空间进行搜索
设置队列oilQueue用以保存待访问节点
设置列表visitedNodes用以保存已访问节点,减少重复搜索的时间
设置success_flag标签来指示搜索是否成功,初始为False。若循环结束success_flag仍为Flase则表示搜索失败,若为True则表示搜索成功。

具体步骤

1、 将初始状态(10, 0, 0)入队, 并加入visitedNodes列表中,表示该节点已访问
2、 若队列不空且success_flag为False,则队头元素出队。否则结束循环,根据success_flag判断是否成功搜索到了目标状态
3、 将该队头元素所有经智能算子变化得到的且未在vistedNodes列表中的元素入队,并加入visitedNodes列表中。且判断当前元素是否为目标状态,若是则将success_flag置为True,跳出循环,否则继续
4、 返回第2步

四、源代码

from queue import Queue
import time


class OilBottleState:
    def __init__(self, A=10, B=0, C=0):
        self.A = A
        self.B = B
        self.C = C

    def __eq__(self, other):
        return self.__dict__ == other.__dict__


class Node:
    def __init__(self, state, findex):
        self.state = state
        # 用来存储父节点的在已访问节点列表中的下标,方便得到搜索路径
        self.findex = findex

    def __eq__(self
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值