商人过河问题_6人过河问题_3商人3随从过河问题_python求全部解

"""
三个商人带了三个随从准备过河,目前只有一条空船(至少需要一人划船),并且最大承重两人,
这时随从商议在河的任意一岸只要商人的数量少于随从的数量,那随从就会杀人越货,
请问商人要怎么安全过河?
"""

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()

结果:

[['随从', '随从'], ['随从'], ['随从', '随从'], ['随从'], ['商人', '商人'], ['商人', '随从'], ['商人', '商人'], ['随从'], ['随从', '随从'], ['商人'], ['商人', '随从']]
[['商人', '随从'], ['商人'], ['随从', '随从'], ['随从'], ['商人', '商人'], ['商人', '随从'], ['商人', '商人'], ['随从'], ['随从', '随从'], ['商人'], ['商人', '随从']]
[['随从', '随从'], ['随从'], ['随从', '随从'], ['随从'], ['商人', '商人'], ['商人', '随从'], ['商人', '商人'], ['随从'], ['随从', '随从'], ['随从'], ['随从', '随从']]
[['商人', '随从'], ['商人'], ['随从', '随从'], ['随从'], ['商人', '商人'], ['商人', '随从'], ['商人', '商人'], ['随从'], ['随从', '随从'], ['随从'], ['随从', '随从']]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章