题目描述
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
如下图所示: 有 9 只盘子,排成 1个圆圈。 其中 8只盘子内装着 8 只蚱蜢,有一个是空盘。 我们把这些蚱蜢顺时针编号为 1 ~ 8。
每只蚱蜢都可以跳到相邻的空盘中, 也可以再用点力,越过一个相邻的蚱蜢跳到空盘中。
请你计算一下,如果要使得蚱蜢们的队形改为按照逆时针排列, 并且保持空盘的位置不变(也就是 1-8 换位,2-7换位,...),至少要经过多少次跳跃?
运行限制
-
最大运行时间:1s
-
最大运行内存: 128M
算法思想
本题目是一个填空且寻优的一道题,很自然的考虑到使用bfs算法进行实现,可以通过建立一个队列来帮助我们辅助解决,当然可以使用Queue模块的queue也行,本文选择采用列表的形式,通过list.append()表示入队,list.pop(0)表示出队,作为替代,先上代码在逐句进行解释和分析
start="012345678"
# 这边使用数字字符串的形式来指代我们队列的结果,0表示这个位置为空
mu_biao="087654321"
# 这个就是我们代码最后要找到的目标
queue=[]
# 构建队列列表
queue.append([start,0])
# 将我们初始的字符串,以及统计状态插入进去,这里0就代表是最初始的,不需要蚱蜢跳
have_find=set()
# 使用不重复的统计的集合进行存储我们遍历过的队列
have_find.add(start)
# 将刚开始的状态读入进去
while len(queue)!=0:
# 开始bfs遍历了,退出条件为队列值没有值时,当然这个是把所有的可能性遍历完都没有找到
# 就会从这里退出,当然我们这里主要还是从下面的break退出的.
vertax=queue.pop(0)
# 出队,获取其相对应的值,存储到vertax里面
cur_queue=vertax[0]
# 因为一个队列里面的单元模块都是[string count],所以取里面的第一个参数就是字符串
count=vertax[1]
# 把这里的count取出来,表示蚱蜢跳的次数
if cur_queue==mu_biao:
# 判断退出条件,如果满足了我们的目标,则直接打印出蚱蜢所要跳的最少次数,然后结束循环
print(count)
break
cur0_pos=0
#如果没有,则先找到当前字符串内为0的位置在哪里,就是下次蚱蜢可以跳的位置
while(cur_queue[cur0_pos]!='0'):
cur0_pos+=1
next_pos=[0]*4
#这里next_pos表示可以跳到0的位置的四只蚱蜢,分别表示-2 -1 1 2用加7,8,1,2加取余的方式
#可以完美获取四只蚱蜢的位置,类似循环队列的思想
next_pos[0]=(cur0_pos+7)%9
next_pos[1]=(cur0_pos+8)%9
next_pos[2]=(cur0_pos+1)%9
next_pos[3]=(cur0_pos+2)%9
for i in range(4):
#这里就是对应每次bfs都是四层的访问,因为有四只可以跳,把这四只跳完才会重新循环
new_queue=list(cur_queue)
#先转换为列表,方便修改蚱蜢飞过的位置
new_queue[cur0_pos]=new_queue[next_pos[i]]
#将0的位置置为蚱蜢原来的位置
new_queue[next_pos[i]]='0'
#将蚱蜢的位置置为0
new_string="".join(new_queue)
#修改完成后,在转换为字符串,丢到集合内去判断是否有这种情况了,这样保证了
#绝对没有重复,同时count是最优的
if new_string not in have_find:
have_find.add(new_string)
queue.append([new_string,count+1])
总结:
基本上注释都把每一句都解释了一遍,所以也不再多赘述了,思想比较好玩的地方就是对于蚱蜢四个位置的处理,刚好蚱蜢都围成了一个圈,形成了一个循环队列,可以适用这种思想,同时将结果转换为整型的字符串的形式也特别的方便,后面做对比,也加深了对于bfs的理解,是一个很好的学习题目.