寻找手机手势解锁共有多少种解法
(1)先分析一下手势解锁必须满足的条件:
1、解锁至少要连四个点
2、每一个点至多只能连接一次
3、不能跳跃连线。先定义9个圆圈分别为数字1-9,如下所示:
7 8 9
4 5 6
1 2 3
比如第一个点选1,那么在4未被选中的情况下是不可以从1直接连接7的。同理还有其他的禁忌,如195,132等等,意思分别是在中间5、2未被选中的情况下,1是不能直接和9、3直接连接的。所有不允许出现的情况在代码中用一个禁忌表来展示。但是,以519,5419等允许的方式举例,若想1和9直接相连,那么1、9中间的5必须在之前就已经连接过。
(2)求解的思路是先穷举所有连接方案,再从所有方案里剔除被禁忌的连接方式。
from itertools import permutations
import numpy as np
class Solution():
def __init__(self,solution_range):
self.solution_range = solution_range #定义解锁需连接solution_range个点
self.lst = permutations(np.array(range(9)) + 1, self.solution_range) #生成solution_range个点的全排列
self.count = 0
self.Tabu = {'19':'5','13':'2','17':'4','28':'5','31':'2','39':'6',
'37':'5','46':'5','64':'5','71':'4',
'73':'5','79':'8','82':'5','91':'5','93':'6','97':'8'} #所有被禁忌的连接方式
def check(self,string): #检查连接方式string是否合法
for item in list(self.Tabu.keys()):
if item in string:
ind = string.index(item)
if (self.Tabu[item] not in string[:ind]):
return False
else:
return True
def solution_list(self): #求解连接solution_range个点的合法连接方式的个数
for item in self.lst:
string = ''.join(map(str,item)) #将全排列后的数字列表转化成全数字的字符串
if self.check(string): #检查合格,计数+1
self.count += 1
solution_num = 0
for i in range(4,10):
solution = Solution(i) #从4-9范围生成solution_range不同的实例
solution.solution_list() #求解
solution_num += solution.count
print('Total solution number is:{}'.format(solution_num))
(3)结果:
Total solution number is:389112
还有几个小练习,后面继续码出来!