如何用python画帆船_渡河问题以及python是如何吸粉的

这是一个相当古老的问题,描述如下。

问题: 一群人要过河。成员包括一个猎人(Hunter)、一只狼(Wolf)、一个爸爸(Father)、一个妈妈(Mother)、两个儿子(Son)、两个女儿(Daughter)。只有一条船(Boat)。 船上最多坐两个人(狼看成一个人),只有猎人、爸爸、妈妈会开船。 下面有几条规则。注意,规则在 岸上 和在 船上 都会发挥效果。 第一,狼要么独处,要么和猎人在一起,否则会吃人。 第二,如果爸爸离开,妈妈会打儿子。即妈妈和儿子不能在没有爸爸的情形下相处。 第三,如果妈妈离开,爸爸会打女儿。即爸爸和女儿不能在没有妈妈的情形下相处。 试给出全员渡河的方案。

问题的抽象: 抽象分几个部分。

1.成员的状态:用英文单词首字母来表示八位成员和一条船的状态,两个儿子分别用S1、S2表示,女儿同理。状态包括0和1两档,其中0代表未渡河,1代表已渡河。用九维向量C=(B,H,W,F,M,S1,S2,D1,D2)来表示所有成员的状态坐标(Coordinate)。例如H=0表示猎人未渡河,B=1表示船在河对岸,F≠M表示爸妈分居河的两岸,C=(0,0,0,0,0,0,0,0,0)表示所有人均未渡河的初始状态。

2.划船的过程:用操作Row来表示划船过程。用R0表示将船从此岸划到彼岸的操作,用R1表示将船从彼岸划到此岸的操作。只有B=0时才能触发操作R0,效果是将船和船上人的状态从0置为1;只有B=1时才能触发操作R1,效果是将船和船上人的状态从1置为0。两个操作交替进行,从R0开始到R0结束,也就是说,渡河方案中操作的数量必然是奇数。例如,R0=(H,W)表示将猎人和狼送到了河对岸,如果之前是初始状态,则C=(1,1,1,0,0,0,0,0,0)。

3.规则的描述:利用前面抽象的结果,我们对规则进行等价描述(注意必须是等价)。

(1)H or F or M in R。

(2)如果H≠W,则F,M,S1,S2,D1,D2=H。如果W in R,则R=(H,W)。

(3)如果F≠M,则S1,S2=F,D1,D2=M。如果F in R,则R≠(F,Di),如果M in R,则R≠(M,Si),其中i=1,2。

4.渡河的方案:我们的目标,就是通过两种操作R0和R1,在规则的约束下,找到点(0,0,0,0,0,0,0,0,0)到达点(1,1,1,1,1,1,1,1,1)的路径。我们希望方案是简单的,即不希望在路径中出现圈。

数学的解答:这类问题可以从两端向中间逼近。逻辑推理过程不赘述。

CrossRiver程序说明:

rows:代表划船成员组合的所有可能情形。

rows=[[1],[3],[4],

[1,2],[1,3],[1,4],[1,5],[1,6],[1,7],[1,8],

[3,4],[3,5],[3,6],

[4,7],[4,8]]

SwitchState:对成员的状态进行切换。

def SwitchState(state):

if state == 0:

return 1

elif state == 1:

return 0

isExistCoord:判断成员的状态坐标是否符合规则。

def isExistCoord(coord):

if coord[1] != coord[2]:

if SwitchState(coord[1]) in coord[3:]:

return False

else:

return True

elif coord[3] != coord[4]:

if coord[5] == coord[3] and coord[6] == coord[3] and coord[7] == coord[4] and coord[8] == coord[4]:

return True

else:

return False

else:

return True

isExistRow:判断在某个状态坐标下能否执行某个row操作。

def isExistRow(coord, row):

for p in row:

if coord[p] != coord[0]:

return False

return True

Row:对于一个状态坐标执行一个row操作,生成新的状态坐标。

def Row(coord, row):

if isExistRow(coord, row) is True:

NewCoord = coord[:]

for p in row:

NewCoord[p] = SwitchState(NewCoord[p])

NewCoord[0] = SwitchState(NewCoord[0])

return NewCoord

CrossRiver:对于给定的起始和终点坐标,寻找可能的路径。BlockedCoords表示路径生成过程中不可以经过的坐标,其中包括已经走过的路径上的坐标,和曾经走过但未能走通的坐标。

def CrossRiver(begin, end, coords):

if begin == end:

return (True, [begin], [])

BlockedCoords = coords[:]

for row in rows:

if isExistRow(begin, row) is True and isExistCoord(Row(begin, row)) is True and not Row(begin, row) in BlockedCoords:

NextCoord = Row(begin, row)

BlockedCoords.append(NextCoord)

RestSteps = CrossRiver(NextCoord, end, BlockedCoords)

if RestSteps[0] is True:

return (True, [begin] + RestSteps[1], [row] + RestSteps[2])

return (False, [], [])

结果:点(0,0,0,0,0,0,0,0,0)到达点(1,1,1,1,1,1,1,1,1)的路径和执行的row操作如下:

[0, 0, 0, 0, 0, 0, 0, 0, 0] [1, 2]

[1, 1, 1, 0, 0, 0, 0, 0, 0] [1]

[0, 0, 1, 0, 0, 0, 0, 0, 0] [1, 5]

[1, 1, 1, 0, 0, 1, 0, 0, 0] [1, 2]

[0, 0, 0, 0, 0, 1, 0, 0, 0] [3, 6]

[1, 0, 0, 1, 0, 1, 1, 0, 0] [3]

[0, 0, 0, 0, 0, 1, 1, 0, 0] [3, 4]

[1, 0, 0, 1, 1, 1, 1, 0, 0] [4]

[0, 0, 0, 1, 0, 1, 1, 0, 0] [1, 2]

[1, 1, 1, 1, 0, 1, 1, 0, 0] [3]

[0, 1, 1, 0, 0, 1, 1, 0, 0] [3, 4]

[1, 1, 1, 1, 1, 1, 1, 0, 0] [4]

[0, 1, 1, 1, 0, 1, 1, 0, 0] [4, 7]

[1, 1, 1, 1, 1, 1, 1, 1, 0] [1, 2]

[0, 0, 0, 1, 1, 1, 1, 1, 0] [1, 8]

[1, 1, 0, 1, 1, 1, 1, 1, 1] [1]

[0, 0, 0, 1, 1, 1, 1, 1, 1] [1, 2]

[1, 1, 1, 1, 1, 1, 1, 1, 1]

最后说一句,python强,无敌!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值