python 穷举算法 - 等分8升水问题

改进:

1-目前只计算出了一种穷举结果,如何将穷举到的所有结果都计算出来。

--------------------

穷举算法:

当规则制定好后,就需要穷举所有可能.

从这些可能中,挑选出最符合的结果。

 

例:等分8升水问题。

建模:

假设三个桶大小[8,5,3],给定状态[8,0,0],输出状态[4,4,0]

状态迁移规则:

1-一次迁移只能从一个桶A到另一个桶B,不能自己到自己(A-A);

2-桶A必须有水。

3-桶B不是满水状态。

4-桶没有刻度,A、B桶至少一个为空或一个为满。

举例:

Status - Change

[8,0,0] - [8,5,5]

[3,5,0] - [5,3,3]

[3,2,3] - [3,8,3]

[6,2,0] - [5,3,2]

[6,0,2] - [8,5,5]

[1,5,2] - [5,3,1]

[1,4,3] - [3,8,1]

[4,4,0]

 

算法设计:

按照状态迁移规则,穷举所有可能。

[src, dst, water]

[water, limit]

1-迁移成功的情况:

先确定从src到dst的water具体值,只能是以下三种情况:

src.water大于dst的limit 且 dst.water=0,water = dst.limit-0

src.water大于dst的limit 且 dst.water有值,water = dst.limit-dst.water

src.water小于dst.limit - dst.water,则 water = src.water

2-迁移不成功的情况:

Src.water = 0 #源空

Dst.limit = dst.water #目的满

3-穷举所有可能的迁移情况:

[src, dst, water]

[8, 5, water]

[8, 3, water]

[5, 8, water]

[5, 3, water]

[3, 8, water]

[3, 5, water]

这里会确定一个先后顺序,因为程序的特点是顺序执行。根据顺序的不同,会产生不同的结果。

4-避免状态循环

用队列记录每一次的状态,并在每一次迁移之前,查找当前状态是否在该队列中。

“要避免出现状态环,就需要记录一次深度遍历过程中所有已经搜索过的状态,形成一个当前搜索已经处理过的状态表,每当生成一个新状态,就先检查是否是状态表中已经存在的状态,如果是则放弃这个状态,回溯到上一步继续搜索。如果新状态是状态表中没有的状态,则将新状态加入到状态表,然后从新状态开始继续深度优先遍历。”

伪代码:

当前状态 = 初始状态

While(1):

    记录迁移之前的状态

    计算一次迁移

    若迁移后的状态在记录中存在

        转到迁移之前的状态

    Else:

记录迁移后的状态

 

算法实现:

***第 1 次循环***

--- deque([[8, 0, 0], [3, 5, 0]])

--- deque([[8, 0, 0], [3, 5, 0], [0, 5, 3]])

--- deque([[8, 0, 0], [3, 5, 0], [0, 5, 3], [5, 0, 3]])

--- deque([[8, 0, 0], [3, 5, 0], [0, 5, 3], [5, 0, 3]])

--- deque([[8, 0, 0], [3, 5, 0], [0, 5, 3], [5, 0, 3]])

--- deque([[8, 0, 0], [3, 5, 0], [0, 5, 3], [5, 0, 3], [5, 3, 0]])

***第 2 次循环***

--- deque([[8, 0, 0], [3, 5, 0], [0, 5, 3], [5, 0, 3], [5, 3, 0]])

--- deque([[8, 0, 0], [3, 5, 0], [0, 5, 3], [5, 0, 3], [5, 3, 0], [2, 3, 3]])

--- deque([[8, 0, 0], [3, 5, 0], [0, 5, 3], [5, 0, 3], [5, 3, 0], [2, 3, 3]])

--- deque([[8, 0, 0], [3, 5, 0], [0, 5, 3], [5, 0, 3], [5, 3, 0], [2, 3, 3]])

--- deque([[8, 0, 0], [3, 5, 0], [0, 5, 3], [5, 0, 3], [5, 3, 0], [2, 3, 3]])

--- deque([[8, 0, 0], [3, 5, 0], [0, 5, 3], [5, 0, 3], [5, 3, 0], [2, 3, 3], [2, 5, 1]])

***第 3 次循环***

--- deque([[8, 0, 0], [3, 5, 0], [0, 5, 3], [5, 0, 3], [5, 3, 0], [2, 3, 3], [2, 5, 1]])

--- deque([[8, 0, 0], [3, 5, 0], [0, 5, 3], [5, 0, 3], [5, 3, 0], [2, 3, 3], [2, 5, 1]])

--- deque([[8, 0, 0], [3, 5, 0], [0, 5, 3], [5, 0, 3], [5, 3, 0], [2, 3, 3], [2, 5, 1], [7, 0, 1]])

--- deque([[8, 0, 0], [3, 5, 0], [0, 5, 3], [5, 0, 3], [5, 3, 0], [2, 3, 3], [2, 5, 1], [7, 0, 1]])

--- deque([[8, 0, 0], [3, 5, 0], [0, 5, 3], [5, 0, 3], [5, 3, 0], [2, 3, 3], [2, 5, 1], [7, 0, 1]])

--- deque([[8, 0, 0], [3, 5, 0], [0, 5, 3], [5, 0, 3], [5, 3, 0], [2, 3, 3], [2, 5, 1], [7, 0, 1], [7, 1, 0]])

***第 4 次循环***

--- deque([[8, 0, 0], [3, 5, 0], [0, 5, 3], [5, 0, 3], [5, 3, 0], [2, 3, 3], [2, 5, 1], [7, 0, 1], [7, 1, 0]])

--- deque([[8, 0, 0], [3, 5, 0], [0, 5, 3], [5, 0, 3], [5, 3, 0], [2, 3, 3], [2, 5, 1], [7, 0, 1], [7, 1, 0], [4, 1, 3]])

--- deque([[8, 0, 0], [3, 5, 0], [0, 5, 3], [5, 0, 3], [5, 3, 0], [2, 3, 3], [2, 5, 1], [7, 0, 1], [7, 1, 0], [4, 1, 3]])

--- deque([[8, 0, 0], [3, 5, 0], [0, 5, 3], [5, 0, 3], [5, 3, 0], [2, 3, 3], [2, 5, 1], [7, 0, 1], [7, 1, 0], [4, 1, 3]])

--- deque([[8, 0, 0], [3, 5, 0], [0, 5, 3], [5, 0, 3], [5, 3, 0], [2, 3, 3], [2, 5, 1], [7, 0, 1], [7, 1, 0], [4, 1, 3]])

--- deque([[8, 0, 0], [3, 5, 0], [0, 5, 3], [5, 0, 3], [5, 3, 0], [2, 3, 3], [2, 5, 1], [7, 0, 1], [7, 1, 0], [4, 1, 3], [4, 4, 0]])

***第 5 次循环***

find it!

 

源代码:

 

# coding=utf-8
from collections import deque

class WaterStatus(object):
    def __init__(self, limit, water):
        self.limit = limit
        self.water = water

def ChangeWater(src, dst):
    if src.water == 0 or dst.water == dst.limit:
        water = 0
    if src.water >= dst.limit - dst.water:
        water = dst.limit - dst.water
    else:
        water = src.water
    src.water -= water
    dst.water += water

if __name__ == '__main__':
    a = WaterStatus(8, 8)
    b = WaterStatus(5, 0)
    c = WaterStatus(3, 0)
    water_list = [a, b, c]
    water_queue = deque()
    water_queue.append([8,0,0])

    cur_status = []
    cnt = 1
    while(1):
        print '*** %d 次循环***' % cnt
        cnt += 1
        if [4, 4, 0] == cur_status:
            print 'find it!'
            break
        for water1 in water_list:
            for water2 in water_list:
                # 记录当前状态,深拷贝deepcopy,创建新的对象
                cur_status = list(water_queue[-1])
                water_list[0].water = cur_status[0]
                water_list[1].water = cur_status[1]
                water_list[2].water = cur_status[2]
                # print water_list[0].water, water_list[1].water, water_list[2].water
                # 计算一次迁移
                if water1.limit != water2.limit:
                    ChangeWater(water1, water2)
                    next_status = [water_list[0].water, water_list[1].water, water_list[2].water]
                    # print 'next_status' , next_status
                    if next_status in water_queue:
                        # print '迁移后的状态在记录中存在,将当前状态转到迁移之前的状态'
                        pass
                    else:
                        # print '记录迁移后的状态,一定要用list()来新建一个对象'
                        cur_status = next_status
                        water_queue.append(list(next_status))
                    # print water1.limit , water2.limit, cur_status
                    print '---',water_queue



 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值