一、题目描述
填入0-9的数字,要求:连续的两个数字不能相邻。(左右、上下、对角都算相邻)
一共有多少种可能的填数方案?
请填写表示方案数目的整数
注意:你填写的应该是一个整数,不要填写任何多余的内容或说明性文字。
二、题目分析及解题思路
思路来源于文章:https://blog.csdn.net/d_l_w_d_l_w/article/details/115453382
因为0-9,10个数字固定出现且仅出现一次,所以使用全排列,将每一种可能的情况都进行判断,如果满足条件,答案加一,如果不满足,答案加0.
对于全排列,使用到itertools模块的函数permutations,输入字符串'0123456789',输出tuple元组。那么怎么讲全排列放入方格中?考虑到使用多维数组。因为我们进行全排列的对象是字符串,所以元组中的数字不是整型而是字符串,需要使用map()函数将字符串变为整数,再使用list强制转换为数列,方便进行切片后放入方格。
注意,因为方格并不规则,所以在第0排第0列以及第2行第3列存入-2,不能存入-1.虽然-1和-2看似都满足条件,但是我们判断数字是否相邻,是看起其差的绝对值是否为1,如果存入-1.会有半数以上正确的答案被排除,从而输出答案为:424,是错误的。
对每一种全排列进行遍历,将全排列进行处理,得到二维数组进行判断是否满足条件。本题中只要发现不满足条件就全部不满足,只有当全部满足时才满足,所以判断不满足条件更加简单。
最后再总结一下整题解题思路:将0-9数字记性全排列,深度遍历解决问题。对全排列转化的二维数组进行遍历,当二维数组不满足条件时,返回0.对二维数组遍历实际上是对数字8个方向进行遍历,判断相邻数字是否连续,判断方法为数字差的绝对值是否为1,如果为1说明数字相邻,不满足条件范围False即不满足条件。如果均满足,返回True。
三、代码
import itertools
ans = 0
move = [[-1,0],[0,1],[0,-1],[1,0],[-1,1],[-1,-1],[1,1],[1,-1]]
def check(m):
def dfs(x,y):
for k in move:
new_x = x + k[0]
new_y = y + k[1]
if new_x<0 or new_x>2 or new_y<0 or new_y>3:
continue
if abs(m[new_x][new_y] - m[x][y]) == 1:
return False
return True
for i in range(3):
for j in range(4):
if not dfs(i,j):
return 0
return 1
for a in itertools.permutations('0123456789'):
m = []
a = (-2,)+a+(-2,)
a = list(map(int,a))
m.append(a[:4])
m.append(a[4:8])
m.append(a[8:])
## print(m)
ans += check(m)
print(ans)