您当前的位置:首页 > 生肖 > 生肖羊

24点算法(24点算法大全及答案)

时间:2024-01-16 20:43:26 作者:旧人陌兮 来源:网友上传

本文目录一览:

Python基础算法案例:24点游戏求解(完美解决括号问题)

目标要求

对于任意给定的四张扑克牌,计算是否有赢得24点游戏的方法(即使用加、减、乘、除四则运算凑成24的方法);如果有的话,列出所有可能的方法。

【24点游戏规则】

在大小王以外的52张牌中,任意抽取其中4张牌。如果通过加、减、乘、除四则运算(可加括号)的方法,将抽到的4张牌算成24,则为胜利;每张牌都必须使用,且只能使用一次。

第一种解法

依据游戏规则,我们可以想到如下解决思路:使用枚举的方法,将所有的计算方法都枚举出来,将四张扑克牌的数字代入到所有的计算方法中得出结果,如果结果为24则为解。

由此,我们得到了第一种解法。在具体实现中:将所有可能的四则运算组合和所有可能的括号组合合并在一起,由此生成所有可能的算式组合。计算某一个牌组时,先计算所有该牌组所有可能的组合方式,并将所有的组合方式带入所有可能的算式组合求解。

 import itertools ​ class CardGaming:     def __init__(self):         self.formula_list = list()  # 存储所有可能的算式         for marks in itertoolsduct(["+", "-", "*", "/"], repeat=3):             for bracket in ["{0}%s{1}%s{2}%s{3}", "({0}%s{1})%s{2}%s{3}", "({0}%s{1}%s{2})%s{3}",                             "{0}%s({1}%s{2})%s{3}",                             "{0}%s({1}%s{2}%s{3})", "({0}%s{1})%s({2}%s{3})", "{0}%s{1}%s({2}%s{3})"]:                 self.formula_listend((bracket % marks)) ​     def solve(self, card_probability):         answer = []         for card_order in set(itertools.permutations(card_probability, 4)):  # 遍历所有可能的不同卡牌顺序(最多24种可能)             for formula in self.formula_list:  # 遍历所有可能的算式(448种可能)                 final_formula = formula.format(*card_order)                 try:                     if round(eval(final_formula), 3) == 24:                         answerend(final_formula)                 except ZeroDivisionError:                     continue         return answer ​ if __name__ == "__main__":     print(CardGaming()lve((3, 3, 8, 8)))  # 输出: 8/(3-8/3)

当前代码在计算每一个牌组的答案时,都需要遍历​4^3*7=448种算式和最多​A44=24种卡牌顺序,即处理最多448*24=10752​种可能性。使用这个解法计算所有可能的扑克牌组合(共计​13^4=28561种解法),需要1906秒(I7 7700,8GB)。

第二种解法

在第一种解法中,计算每一个牌组的答案时,处理的可能性中有很多重复的情况,例如“A+B-C+D”、“D-C+B+A”、“D+A-C+B“等。这就极大地拖累了我们的运算速度。但是,要在第一种解法的基础上来合并这些不同的情况,需要同时考虑符号、括号和卡牌顺序,十分复杂。

因此,我们可以从另外一个角度来解决这个问题。

通过观察我们可以发现,无论什么算式,本质上都是按着一定的顺序,对4张扑克牌的数值进行三次运算;而每一次运算,都是从尚未用过的扑克牌以及之前的运算结果中选择2个进行运算。所以,我们可以将所有算式归纳为:

从4张牌中任意抽取2个进行任意运算,将未抽取的2张牌和运算结果组合成包含3个数值的新列表;在新列表中任意抽取2个进行任意运算,将未抽取的1张牌和运算结果组成包含2个数值的新列表;对新列表中的2个数值进行任意运算得出结果,如果结果为24则为解。

由此,我们得到了第二种算法。在具体实现中,我们主要注意如下几点:

因为不再枚举算式,所以我们也不再需要使用低效的eval()函数运行算式。因为如果在运算过程中生成算式,会增加很多运算量,所以我们只在求出解后反向生成解的算式(哪怕这样生成算式会更困难,但是需要生成的次数大大减少)。

 def solve(card_probability):     card_probability = list(card_probability)  # 生成临时列表     answer = []     for combine_1 in set(itertoolsbinations(card_probability, 2)):  # 在临时列表的4个数中任意抽取2个数         for answer_1 in all_maybe_count_answer(combine_1[0], combine_1[1]):             card_list_1 = copy.deepcopy(card_probability)             card_list_1.remove(combine_1[0])  # 从临时列表移除抽到的数1             card_list_1.remove(combine_1[1])  # 从临时列表移除抽到的数2             card_list_1end(answer_1)  # 添加计算结果到临时列表             for combine_2 in set(itertoolsbinations(card_list_1, 2)):  # 在临时列表的3个数中任意抽取2个数                 for answer_2 in all_maybe_count_answer(combine_2[0], combine_2[1]):                     card_list_2 = copy.deepcopy(card_list_1)                     card_list_2.remove(combine_2[0])  # 从临时列表移除抽到的数1                     card_list_2.remove(combine_2[1])  # 从临时列表移除抽到的数2                     card_list_2end(answer_2)  # 添加计算结果到临时列表                     for combine_3 in set(itertoolsbinations(card_list_2, 2)):  # 抽取临时列表剩下的2个数                         for answer_3 in all_maybe_count_answer(combine_3[0], combine_3[1]):                             if round(answer_3, 3) == 24:                                 answerend(total_formula(card_probability, combine_1, answer_1, combine_2,                                                             answer_2, combine_3, answer_3))  # 生成完整算式     return answer ​ ​ if __name__ == "__main__":     start_time = time.time()     for cards in list(itertoolsduct([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], repeat=4)):         solve(cards)     print("计算时间:", time.time() - start_time)

(其中all_maybe_count_answer函数计算两个参数进行四则运算的所有可能结果;total_formula函数依据中间变量生成完整计算公式)

运行结果:

 计算时间: 136.27595901489258

这种接法在第一次四则运算时,有种C24=6抽取结果,有6种运算结果(减法和除法因顺序不同有2个结果);在第二次四则运算时,有种C23=3抽取结果,有6种运算结果;在第三次四则运算时,有C22=1种抽取结果,有6种运算结果。

因此,这种算法在求一个扑克牌组的解时,仅需要考虑​​C24*6*C23*6*C22*6=3888种可能性。使用这个解法计算所有可能的扑克牌组合,需要136秒(I7 7700,8GB),比第一种解法快了10倍以上。

完整源代码详见扩展链接

软件开发:计算机编程的算法有哪些?

编程语言、数据结构和算法可以说是学习软件开发的三大类,要问学习软件开发学什么,核心就是这三类东西。前面大致介绍了编程语言和数据结构的种类,今天我们再来简单罗列一下计算机编程的算法,让准备学习软件开发的同学对软件开发所要学习的内容有了结构性的印象,便于建立学习软件开发的信念感。

计算机编程的算法有很多种,常见的有:

1.冒泡排序

2.快速排序

3.归并排序

4.插入排序

5.选择排序

6.堆排序

7.希尔排序

8.归并排序

9.桶排序

10.计数排序

11.基数排序

12.贪心算法

13.动态规划

14.分治算法

15.图论算法

16.哈希表算法

17.二叉树算法

18.回溯算法

19.DFS算法

20.BFS算法

21.并查集算法

22.剪枝算法

23.蒙特卡罗算法

24.快速搜索算法

25.AI算法

26.模拟退火算法

27.遗传算法

28.粒子群算法

29.神经网络算法

30.决策树算法

31.支持向量机算法

32.KNN算法

33.K-Means算法

34.主成分分析算法

35.线性回归算法

36.非线性回归算法

37.聚类分析算法

38.协方差分析算法

39.时间序列分析算法

40.蒙特卡罗模拟算法

41.布尔运算算法

42.图像处理算法

43.数据压缩算法

44.加密解密算法

45爬虫算法

46.大数运算算法

47.字符串匹配算法

48.机器学习算法

49.深度学习算法

50.强化学习算法

大家不要看到这里罗列了这么多算法的种类就望而却步,它又不是让你一次性全部要学会的,学习算法是融合进编程语言和数据结构中,需要循序渐进,这些算法不全是初阶的,多数是中阶和高阶的,像机器学习、深度学习等,这些是人工智能这种当下主流和高阶的项目需要用到的东西,大家慢慢掌握,不要急。要知道,学好计算机编程是一件很炫酷的事,它会让你知道如何创造一个世界,会让你感受到造物主的思想,所以,不要悲观,好好去学习吧。

热门推荐