"""
三个商人带了三个随从准备过河,目前只有一条空船(至少需要一人划船),并且最大承重两人,
这时随从商议在河的任意一岸只要商人的数量少于随从的数量,那随从就会杀人越货,
请问商人要怎么安全过河?
"""
from collections import Counter
from random import sample, randint
class Solution:
"""解决问题的方案类"""
def __init__(self):
"""初始化属性"""
self.left = ['商人'] * 3 + ['随从'] * 3 # 后面用到了Counter,所以这里可以用字符串表示,不用0,1表示,更直观一点
self.left_checkpoint = [] # 左边的存档,用于试错后恢复
self.right = []
self.right_checkpoint = []
self.result = [[]] # 结果,给个初始值是为了避免out of index的情况,取结果的时候切片即可
self.result_checkpoint = []
self.r_direction = True # True为右,False为左
def go(self):
"""渡河"""
if self.r_direction: # 向右渡河
boat = sample(self.left, 2)
for i in boat:
self.left.remove(i)
self.right.append(i)
else: # 向左渡河
if len(self.right) > 1: # 这里判断是为了避免sample取的时候越界(从1个里面取2个)
boat = sample(self.right, randint(1, 2))
else:
boat = sample(self.right, 1)
for i in boat:
self.right.remove(i)
self.left.append(i)
return boat
def judge(self):
"""判断"""
if self.left and self.right:
left_counter = Counter(self.left)
right_counter = Counter(self.right)
if (left_counter['商人'] and left_counter['商人'] < left_counter['随从']) or \
(right_counter['商人'] and right_counter['商人'] < right_counter['随从']):
return False
return True
def checkpoint(self):
"""检查点"""
self.left_checkpoint, self.right_checkpoint, self.result_checkpoint = \
self.left.copy(), self.right.copy(), self.result.copy()
def reset(self):
"""读档"""
self.left, self.right, self.result = \
self.left_checkpoint.copy(), self.right_checkpoint.copy(), self.result_checkpoint.copy()
def get_result(self):
"""模拟渡河过程,获取结果"""
while len(self.right) < 6:
self.checkpoint() # 存档
boat = self.go() # 渡河
boat.sort()
if self.judge() and boat != self.result[-1]: # 这里判断是为了避免相同的人来回的情况,以求尽可能少的解
self.r_direction = not self.r_direction # 调转船头
self.result.append(boat)
else:
self.reset() # 读档
return self.result[1:]
def main():
"""主函数"""
repeat = 10000 # 重复执行次数
result_set = set() # 解的集合
solution = Solution()
for _ in range(repeat):
result = solution.get_result()
result_set.add(str(result))
solution.__init__()
print(f'经{repeat}次执行,共得到{len(result_set)}种不同的结果,结果如下:', end='\n\n')
for result in result_set:
print(result)
if __name__ == '__main__':
main()
结果:
[['随从', '随从'], ['随从'], ['随从', '随从'], ['随从'], ['商人', '商人'], ['商人', '随从'], ['商人', '商人'], ['随从'], ['随从', '随从'], ['商人'], ['商人', '随从']]
[['商人', '随从'], ['商人'], ['随从', '随从'], ['随从'], ['商人', '商人'], ['商人', '随从'], ['商人', '商人'], ['随从'], ['随从', '随从'], ['商人'], ['商人', '随从']]
[['随从', '随从'], ['随从'], ['随从', '随从'], ['随从'], ['商人', '商人'], ['商人', '随从'], ['商人', '商人'], ['随从'], ['随从', '随从'], ['随从'], ['随从', '随从']]
[['商人', '随从'], ['商人'], ['随从', '随从'], ['随从'], ['商人', '商人'], ['商人', '随从'], ['商人', '商人'], ['随从'], ['随从', '随从'], ['随从'], ['随从', '随从']]