蛇形排列的种数

95 篇文章 2 订阅

蛇形排列的种数

问题:
在4×4方格中按蛇形排列放置1-16个数字,以下是二种放置方法:

13  12   1   2
14  11   4   3
15  10   5   6
16   9   8   7

1   2  13  12
4   3  14  11
5  16  15  10
6   7   8   9

计算总共有多少种放置方法,并打印其中的20种放置方法。
这应该是一道竞赛题的变种。解题思路如下。
1、分清楚循环(把标志1放在4x4方格中的任意一个格内,有16种情况)和递归(找出在上述每一种情况下其它标志2-16放置的各种可能性),这个相当关键,详见程序。
2、设置标志前先看选点是否越界或重复放置。
3、递归返回后,要清除标志,为再次放置提供条件。
4、首标志设为1,之后的标志在此基础上累加,为打印标志做好准备。
5、每次放置到标志16后,说明一种放置成功,返回到下一个放置方法的搜索。

def dfs(section, x, y):
    global n
    if section == 16:   # 递归返回条件,即一种放置方法成功后返回寻找另外一种放置方法,直至找到所有放置方法
        n += 1
        if n < 21:
            show()
        return
    for s in step:
        lay_x, lay_y = x + s[0], y + s[1]
        # 检查移动是否越出边界
        if lay_x < 0 or lay_y < 0 or lay_x > 3 or lay_y > 3 or mark[4 * lay_y + lay_x] > 0:
            continue
        mark[lay_y * 4 + lay_x] = section+1  # 设置放置标志:首标志之后的标志为2-16
        dfs(section + 1, lay_x, lay_y)       # 在放置第一个数的位置(下标0-15中的任意一个)确定后,进入后续位置的递归
        mark[lay_y * 4 + lay_x] = 0


def show():
    for _j in range(4):
        for _i in range(4):
            print("{0:2}".format(mark[_j * 4 + _i]), end="  ")
        print("")
    print("")


if __name__ == '__main__':
    step = [[0, 1], [0, -1], [1, 0], [-1, 0]]  # 向四周移动
    n = 0
    mark = [0 for _ in range(16)]
    for j in range(4):
        for i in range(4):
            mark[j * 4 + i] = 1     # 设置放置标志:一种放置方法的首标志为1
            dfs(1, i, j)            # 在任意位置(下标0-15的任意一个)放置第一个数(1)开始递归搜索
            mark[j * 4 + i] = 0     # 重新搜索前先清除标志
    print("共有{0}种放置方法。".format(n))

D:\Python\Python38\python.exe D:/Python/study/20201220.py
 1   8   9  16  
 2   7  10  15  
 3   6  11  14  
 4   5  12  13  

 1   8   9  10  
 2   7  16  11  
 3   6  15  12  
 4   5  14  13  

 1   8   9  10  
 2   7  12  11  
 3   6  13  16  
 4   5  14  15  

 1   8   9  10  
 2   7  12  11  
 3   6  13  14  
 4   5  16  15  

 1  16  15  14  
 2   7   8  13  
 3   6   9  12  
 4   5  10  11  

 1  16  13  12  
 2  15  14  11  
 3   6   7  10  
 4   5   8   9  

 1  14  13  12  
 2  15  16  11  
 3   6   7  10  
 4   5   8   9  

 1  14  15  16  
 2  13  12  11  
 3   6   7  10  
 4   5   8   9  

 1  10  11  12  
 2   9   8  13  
 3   6   7  14  
 4   5  16  15  

 1  16  11  10  
 2  15  12   9  
 3  14  13   8  
 4   5   6   7  

 1  12  11  10  
 2  13  16   9  
 3  14  15   8  
 4   5   6   7  

 1  12  11  10  
 2  13  14   9  
 3  16  15   8  
 4   5   6   7  

 1  14  15  16  
 2  13  10   9  
 3  12  11   8  
 4   5   6   7  

 1  14  13  12  
 2  15  10  11  
 3  16   9   8  
 4   5   6   7  

 1  12  13  16  
 2  11  14  15  
 3  10   9   8  
 4   5   6   7  

 1  12  13  14  
 2  11  16  15  
 3  10   9   8  
 4   5   6   7  

 1  16  15  14  
 2  11  12  13  
 3  10   9   8  
 4   5   6   7  

 1   6   7   8  
 2   5  10   9  
 3   4  11  12  
16  15  14  13  

 1   8   9  10  
 2   7   6  11  
 3   4   5  12  
16  15  14  13  

 1  16  15  14  
 2   3  12  13  
 5   4  11  10  
 6   7   8   9  

共有552种放置方法。

Process finished with exit code 0

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值