Algorithm 算法思维指导(4-4方程)
我最近看到了一个逻辑/数学问题,名为4-Fours,其中需要使用4-Fours和一系列运算符来创建等于所有整数0到N的方程 你将如何着手编写一个优雅的算法来提出,比如说第一个100 我从创建基本计算开始,比如4-4、4+4、4x4、4/4、4!,Sqrt 4并将这些值设为整数 然而,我意识到这将是一个蛮力方法来测试组合,看看它们是否相等,0,然后1,然后2,然后3等等 然后,我想找到所有可能的上述值的组合,检查结果是否小于100,填充一个数组,然后对其进行排序……同样效率低下,因为它可能会找到1000个大于100的数字 任何关于如何处理这样的问题的帮助都是有帮助的…不是实际的代码…而是如何思考这个问题Algorithm 算法思维指导(4-4方程),algorithm,computation-theory,Algorithm,Computation Theory,我最近看到了一个逻辑/数学问题,名为4-Fours,其中需要使用4-Fours和一系列运算符来创建等于所有整数0到N的方程 你将如何着手编写一个优雅的算法来提出,比如说第一个100 我从创建基本计算开始,比如4-4、4+4、4x4、4/4、4!,Sqrt 4并将这些值设为整数 然而,我意识到这将是一个蛮力方法来测试组合,看看它们是否相等,0,然后1,然后2,然后3等等 然后,我想找到所有可能的上述值的组合,检查结果是否小于100,填充一个数组,然后对其进行排序……同样效率低下,因为它可能会找到1
谢谢 我认为暴力解决方案是唯一的出路。
这背后的原因是,每个数字都有不同的到达方式,到达某个
x
可能与到达x+1
无关
话虽如此,通过尽可能使用明显的动作,您可能会使暴力解决方案更快一些。例如,如果我用“4”三次达到20(
4*4+4
),很明显达到16、24和80。持有一个100位的数组并标记达到的数字类似于子集和问题,可以使用以下递归公式来解决:
D(0,0) = true
D(x,0) = false x!=0
D(x,i) = D(x-4,i-1) OR D(x+4,i-1) OR D(x*4,i-1) OR D(x/4,i-1)
通过使用DP技术计算上面的数字,很容易找到使用这4个数字可以生成哪些数字,通过回溯解决方案,您可以找到每个数字是如何生成的
此方法的优点(当使用DP实现时)是不需要多次重新计算多个值。我不确定它是否真的对4 4有效,但我相信从理论上讲,对于这个问题的一个较少限制的推广来说,它可能是一个显著的改进。这个答案只是Amit的一个扩展。 基本上,您的操作是:
n
,计算表达式(n)
-如下所示的(表达式,值)对列表:
(对于固定的n
,在列表中仅存储一个计算结果为任何给定值的表达式)
n
4s(即4、44、444、4444)的串联来初始化列表i
从1到n-1
,以及每个允许的二进制运算符op
,添加表达式(和值)e1 op e2
,其中e1
在表达式(i)
中,而e2
在表达式(n-i)
、Sqrt
、-
等。示例二进制运算符为+-*/^
等。如果允许,您可以轻松地将此方法扩展到具有更多参数的运算符
对于任何给定的
n
,您可以在步骤3中做一些更聪明的事情,永不停止。在所有j
的表达式(j)
完成之前,简单方法(如上所述)不会开始计算表达式(i)
。这要求我们知道何时停止。另一种方法是为每个n
构建具有特定最大长度的表达式,然后如果需要(因为没有找到特定的值),可以在外部循环中扩展最大长度。这是一个有趣的问题。这里发生了两件不同的事情。一个问题是如何描述进入算术表达式的操作和操作数序列。使用括号来建立运算顺序是相当混乱的,因此我建议将表达式看作是一组运算和操作数,比如4-4的-4 4
,(4*4)+4的+4*4
,(4+4)*4的*4+4
,等等。这就像HP计算器上的反向波兰符号。这样你就不必担心括号了,当我们构建越来越大的表达式时,拥有表达式的数据结构将在下面有所帮助
现在我们转向构建表达式的算法。在我看来,动态规划在这种情况下不起作用,因为(例如)要构造一些介于0到100之间的数字,可能需要暂时超出该范围
我认为,更好的概念化问题的方法是在图上进行广度优先搜索(BFS)。从技术上讲,这个图是无限的(所有的正整数,或所有的整数,或所有的有理数,这取决于你想得到的详细程度),但在任何时候你只有一个图的有限部分。稀疏图数据结构是合适的
图上的每个节点(数字)都有一个与之相关联的权重、到达该节点所需的最小4个数,以及实现该结果的表达式。最初,您只需要从节点(4)开始,用与之相关联的数字1(用一个4表示4)和简单表达式“4”。你也可以投(44)重2,投(444)重3,投(4444)重4
要构建更大的表达式,请将所有不同的操作应用于这些初始节点。例如,一元否定、阶乘、sq