问题描述:
河左岸有三个修道士,三个野人和一条船,假定船最多只能运两个人,且任何岸边的野人数目不得超过修道士,否则修道士就会被野人吃掉。
如何才能把修道士和野人都运到右岸?
Savage.rb
#记录状态
class Status
@@StatusList = Array.new
@@Pos = -1
attr_writer :nSavage #岸边野人的数量,全部到对岸为0
attr_writer :nBoanerges #岸边传教士的数量,全部到对岸为0
attr_writer :nSide #船的位置,在此岸为-1,对岸为1
attr_writer :nMoveSavage #渡河的野人的数量,用于递归时记录操作状态
attr_writer :nMoveBoanerges #渡河的传教士的数量,用于递归时记录操作状态
attr_reader :nSavage
attr_reader :nBoanerges
attr_reader :nSide
attr_reader :nMoveSavage
attr_reader :nMoveBoanerges
def initialize()
@nSavage = 3
@nBoanerges = 3
@nSide = -1
@nMoveSavage = 0
@nMoveBoanerges = 0
end
def Status.getList()
return @@StatusList
end
def Status.getPos()
return @@Pos
end
def Status.addStatus(stat)
@@StatusList.push(stat)
@@Pos += 1
end
def Status.delStatus()
@@StatusList.pop()
@@Pos -= 1
end
end
class Ship
def Ship.hasNextStep(stat)
store = [[],[],[],[],[]]
if stat.nSide == -1 then
store[0][SAVAGE] = 2
store[0][BOANERGES] = 0
store[1][SAVAGE] = 1
store[1][BOANERGES] = 1
store[2][SAVAGE] = 0
store[2][BOANERGES] = 2
store[3][SAVAGE] = 1
store[3][BOANERGES] = 0
store[4][SAVAGE] = 0
store[4][BOANERGES] = 1
elsif stat.nSide == 1
store[0][SAVAGE] = 0
store[0][BOANERGES] = 1
store[1][SAVAGE] = 1
store[1][BOANERGES] = 0
store[2][SAVAGE] = 0
store[2][BOANERGES] = 2
store[3][SAVAGE] = 1
store[3][BOANERGES] = 1
store[4][SAVAGE] = 2
store[4][BOANERGES] = 0
end
iStart = 0
if stat.nMoveSavage == 0 && stat.nMoveBoanerges == 0
iStart = 0
else
for iStart in 0...DEEP
puts iStart
if stat.nMoveSavage == store[iStart][SAVAGE] && stat.nMoveBoanerges == store[iStart][BOANERGES]
break
end
end
iStart += 1
end
if (iStart < DEEP)
i = 0
for i in iStart...DEEP
nSideSavage = stat.nSavage + stat.nSide * store[i][SAVAGE]
nSideBoanerges = stat.nBoanerges + stat.nSide * store[i][BOANERGES]
nBesideSavage = 3 - nSideSavage
nBesideBoanerges = 3 - nSideBoanerges
#传教士数量大于等于野人或为零
if ((nSideSavage <= nSideBoanerges || nSideBoanerges == 0) &&
(nBesideSavage <= nBesideBoanerges || nBesideBoanerges == 0) &&
nSideSavage >= 0 && nSideBoanerges >= 0 && nBesideSavage >= 0 && nBesideBoanerges >= 0) then
#如果本此解等于上次,放弃
if Status.getPos > 0
if (Status.getList()[Status.getPos - 1].nMoveBoanerges == store[i][BOANERGES] &&
Status.getList()[Status.getPos - 1].nMoveSavage == store[i][SAVAGE])
next
end
end
break
end
end
if i < DEEP
stat.nMoveSavage = store[i][SAVAGE]
stat.nMoveBoanerges = store[i][BOANERGES]
return true
end
end
return false;
end
#递归函数
def Ship.find(stat)
if hasNextStep(stat)
pNew = Status.new
pNew.nSavage = stat.nSavage + stat.nMoveSavage * stat.nSide
pNew.nBoanerges = stat.nBoanerges + stat.nMoveBoanerges * stat.nSide
pNew.nSide = stat.nSide * -1
pNew.nMoveSavage = 0
pNew.nMoveBoanerges = 0
Status.addStatus(pNew)
if pNew.nSavage == 0 && pNew.nBoanerges == 0
Status.delStatus()
return true
end
return find(pNew)
else
if Status.getPos == 0
return false
end
Status.delStatus()
return find(Status.getList()[Status.getPos])
end
return true
end
end
initStat = Status.new
Status.addStatus(initStat)
if (Ship.find(initStat))
puts "渡河过程如下:"
Status.getList().each do |stat|
print "下次渡河方向:", (stat.nSide == -1) ? "-->" : "<--", " 人数:野人", stat.nMoveSavage, " 传教士", stat.nMoveBoanerges, " 当前此岸野人数:", stat.nSavage, " 传教士数:", stat.nBoanerges, "/n"
end
else
puts "此题无解"
end
print "Press ENTER to return."
$stdin.gets