题目👇
(1)编写递归代码解答汉诺塔问题:据说古代有一个梵塔,塔内有三个底座A、B、C,A 座上有64 个盘子,盘子大小不等,大的在下,小的在上。有一个和尚想把这64 个盘子从A 座移到C 座,但每次只能允许移动一个盘子。在移动盘子的过程中可以利用B 座,但任何时刻3 个座上的盘子都必须始终保持大盘在下、小盘在上的顺序。如果只有一个盘子,则不需要利用B 座,直接将盘子从A 移动到C 即可。编写函数,接收一个表示盘子数量的参数和分别表示源、目标、临时底座的参数,然后输出详细移动步骤和每次移动后三个底座上的盘子分布情况。
函数定义如下:num表示多少个盘子, src表示原底座‘A’,dst表示目标底座’C’,temp表示中间的临时底座’B’。
底座上的盘子可用列表表示,num个大小不一的盘子可用0~(num-1)这些数字表示,则初始状态下’A’底座的列表为[num-1,num-2,…,2,1,0],’B’底座的列表为空,‘C’底座的列表为空。
def hannoi(num, src, dst, temp=None):
(2)编写函数,求解八皇后问题。(使用yield)
(3)编写函数,求解八皇后问题。(不使用yield)
解题思路👇
(1)题目要求用列表来表示某底座上有多少个盘子,所以我们放盘子就append在列表末尾加一个元素,拿走盘子就是pop弹出列表最后一个元素。
另外汉诺塔问题的本质就是递归,把问题拆分成三步,第一步是把A上的n-1个盘子移动到B,再把A的最底下的盘子移到C,再把B上的n-1个盘子移到C,如此一来这n-1个盘子也可以想刚才这么移动,就进入了一个递归模式,另外要注意设置递归终止条件,否则栈会爆炸的。
(2)使用回溯法来解决八皇后问题,意思就是一个一个按顺序放置棋子,放置完一个后就去遍历放完这个棋子之后的所有可能,找到符合条件的放置方法直到8个棋子都放完,遍历过后就回溯到上一步,更改上一步的放置方法,继续遍历剩余的可能情况。使用yield来生成题解的序列进而递归生成所有符合条件的题解序列。
(3)思路和(2)相同,同样使用回溯法来解决问题,区别在于不使用yield来生成题解的序列进而递归生成所有符合条件的题解序列而是使用return直接返回。
关于python中yield的用法可以参考这篇博客:python中yield的用法详解——最简单,最清晰的解释_mieleizhi0522的博客-CSDN博客_yield
参考代码👇
#coding:utf-8
#author:Mitchell
#part1:编写递归代码解答汉诺塔问题:据说古代有一个梵塔,塔内有三个底座A、B、C,A 座上有64 个盘子,盘子大小不等,大的在下,小的在上。
#有一个和尚想把这64 个盘子从A 座移到C 座,但每次只能允许移动一个盘子。在移动盘子的过程中可以利用B 座,但任何时刻3 个座上的盘子都必须始终保持大盘在下、小盘在上的顺序。如果只有一个盘子,则不需要利用B 座,直接将盘子从A 移动到C 即可。
#编写函数,接收一个表示盘子数量的参数和分别表示源、目标、临时底座的参数,然后输出详细移动步骤和每次移动后三个底座上的盘子分布情况。
#函数定义如下:num表示多少个盘子, src表示原底座‘A’,dst表示目标底座’C’,temp表示中间的临时底座’B’
#底座上的盘子可用列表表示,num个大小不一的盘子可用0~(num-1)这些数字表示,则初始状态下’A’底座的列表为[num-1,num-2,…,2,1,0],’B’底座的列表为空,‘C’底座的列表为空。
def hannoi(num, src, temp, dst, A, B, C):
if num==1:
dst.append(src.pop())
print(A,'--->',C)
print(a,b,c)
else:
hannoi(num-1,src,dst,temp,A,C,B)
hannoi(1,src,temp,dst,A,B,C)
hannoi(num-1,temp,src,dst,B,A,C)
num=int(input('请输入盘子个数:'))
a=[num-i-1 for i in range(num)]
b=[]
c=[]
print(a,b,c)
hannoi(num,a,b,c,'A','B','C')
#part2:编写函数,求解八皇后问题。(使用yield)
#判断函数
def isAllowed(A):
for i in range(8):
if sum(A[i])>=2:
return False
if sum([A[j][i] for j in range(8)])>=2:
return False
if sum([A[i+j][j] for j in range(8-i)])>=2:
return False
if sum([A[j][i+j] for j in range(8-i)])>=2:
return False
if sum([A[j][i-j] for j in range(i+1)])>=2:
return False
if sum([A[i+j][7-j] for j in range(8-i)])>=2:
return False
return True
def eight_quene(A,num):
if num==8:
yield A
else:
for i in range(num,8):
for j in range(8):
if A[i][j]==0:
A[i][j]=1
if not isAllowed(A):
A[i][j]=0
continue
#得到生成器里下一步的所有结果
for result in eight_quene(A,num+1):
yield result
A[i][j]=0
#棋盘初始化
A=[[0, 0, 0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0]]
for result in eight_quene(A,0):
#打印出符合条件的棋盘分布图
for i in range(8):
print(result[i])
print()
#part3:编写函数,求解八皇后问题。(不使用yield)
def eight_quene(A,num):
if num==8:
for i in range(8):
print(A[i])
print()
else:
for i in range(num,8):
for j in range(8):
if A[i][j]==0:
A[i][j]=1
if not isAllowed(A):
A[i][j]=0
continue
eight_quene(A,num+1)#放置对应棋子,继续递归
A[i][j]=0 #回溯
#实例化
A=[[0, 0, 0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0]]
eight_quene(A,0)