Python:每日一题之剪邮票(BFS全排列)

如【图1.jpg】, 有12张连在一起的12生肖的邮票。

现在你要从中剪下 5 张来,要求必须是连着的。

(仅仅连接一个角不算相连) 比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。

请你计算,一共有多少种不同的剪取方法。

思考:

思路:暴力求全排列+检查连通性。
        (1)用递归暴力列出所有可能的排列:从12个数中选5个数进行全排列。
        (2)判断这5个数是否连通。
算法复杂度:12*11*10*9*8=121/7=95040
可行!
判断2个数是否连通
小技巧:
        ·在原图中向上为-4,向下为+4,向左为-1,向右为+1,但是遇到34578这种4+1=5,这种情况不符合,所以重构一下原图。
        ·向上为-5,向下为+5,向左为-1,向右为+1。

判断图中的{2,3,4,8,9}是否连通。用队列:
        •2进队列:当前队列是(2);
        •2的邻居进(push)队列:当前队列是(2 3);
        •弹出(pop)2:当前队列是(3);
        •3的邻居进队列:当前队列是(348);
        •弹出3;当前队列是(48)
        •4的邻居进队列:当前队列是(489)
        •弹出4:当前队列是(89)
        •8没有没处理过的邻居了。·弹出8:当前队列是(9)·弹出9;
        •队列空。
如果5个数都进过队列,它们就是连通的。 

参考代码:

from queue import *
def bfs():    #a[0]~a[4]这前5个数是递归出的5个数,用BFS判断是否连通
  vis=[0]*5   #用来标记5个数的状态,判断其中某个数是否已经用队列处理过
  p=0    #进队列的个数,如果5个数都进过队列,说明这五个数连通
  q=Queue()  #创建队列
  q.put(0)   #进队列
  vis[0]=1   #标记,表示 0 被队列处理过了
  while not q.empty(): #是否为空
    i=q.get()  #得到队列的第一个数
    p+=1
    for j in range(5):  
      if vis[j]==0:   #j 没有用队列处理过
        for k in (-1,1,-5,5):  #k 是上下左右四个方向
          if a[i]+k==a[j]:  #与 j 在 k 方向上连接
            q.put(j)
            vis[j]=1   #进队列了
  if p==5:
    return True
  else:
    return False

def perm(s,t):
  global num
  if s==5:   #得到一个 5 个数的全排列,用bfs判断 5 个数是否连通
    if bfs()==True:
      num+=1
  else:
    for i in range(s,t+1):
      a[s],a[i]=a[i],a[s] #交换
      perm(s+1,t)
      a[i],a[s]=a[s],a[i]

a=[1,2,3,4,6,7,8,9,11,12,13,14]
num=0    #统计排列数
perm(0,11)   #求从第 0 个数到第 11 个数的全排列
print(num//120)
#print(116) 最终答案

排列转化为组合num//5x4x3x2x1,分母是选的某几个数,5个数就是5的阶乘,4个数就是4个数的阶乘

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力的敲码工

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值