改进:
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