Algorithm 数字数组中的表达式

Algorithm 数字数组中的表达式,algorithm,math,data-structures,np,np-hard,Algorithm,Math,Data Structures,Np,Np Hard,给你三样东西 1) “n”个正整数和负整数的数组。 2) 一个数字“x”。 3) 运算符:“+”、“-”、“%”、“/” 使用数组形成一个表达式,这样当您对它求值时,结果将变成“x” 例如,考虑数组[5,3,-1,6,2,3]和x=2,一个可能的解决方案是 5/3+(-1)+6/2-1 假设5/3的结果是1(总是整数除法) 我有一个更复杂的变体 在这个问题的复杂变体中,假设BODMASS规则不适用。因此,在任何时候,您遍历元素'm',就得到了中间结果'y'。您可以对“y”和a[m+1]应用任何运

给你三样东西

1) “n”个正整数和负整数的数组。 2) 一个数字“x”。 3) 运算符:“+”、“-”、“%”、“/”

使用数组形成一个表达式,这样当您对它求值时,结果将变成“x”

例如,考虑数组[5,3,-1,6,2,3]和x=2,一个可能的解决方案是

5/3+(-1)+6/2-1

假设5/3的结果是1(总是整数除法)

我有一个更复杂的变体

在这个问题的复杂变体中,假设BODMASS规则不适用。因此,在任何时候,您遍历元素'm',就得到了中间结果'y'。您可以对“y”和a[m+1]应用任何运算符

例如,在变体1中

5+3-2/2=7(2/2先评估,所以5+3-1)

在变体2中

5+3-2/2=3(5+3=8。数组减少为8-2/2。现在,8-2=6。数组减少为6/2,计算结果为3)

算法/数学/DS专家


这是一个NP难问题吗?

有4个运算符,因此对于一组n项,有4^(n-1)个可能的值。您可以构建搜索空间的图形,其中每个路径表示一组运算符值,终点是计算结果

在所有这些终点中,只有那些给出正确答案的终点才是正确的终点

但是,请注意,如果从端点开始,则可以向后遍历;只有当您有一组有效的运算符时,才会以第一个值结束

从两端穿过它,两个计算将在中间相遇。这是一个更小的空间,每个方向4^(n/2)=2^n。为了匹配这两组答案,您需要对中间的列表进行排序,尽管您可能希望在每一步都这样做,以允许您避免重复路径。在这一点上,它看起来很像一个迷宫穿越

一个已知的NP完全问题是of,这是“确定给定布尔公式的变量是否可以以使公式计算为真的方式分配的问题”。我怀疑,由于搜索空间明显大于布尔可满足性问题的搜索空间,并且由于解决方案也会确定公式是可满足的(因此至少与解决可满足性一样困难),那么问题应该是NP完全的

从迷宫的意义上讲,值偏离零的部分解不太可能是正确的解,并且给定参数的初始扫描,应该清楚大小的限制(即所有倍数),这在布尔问题中不是这样的

编辑:澄清我在开头提到的树。假设我们的名单是

 1 ? 2 ? 5 = X
那么图表是这样的:

 r1 -->  r2  ---> r3 (X)

 1  +2    3  +5    8
             -5   -2
             *5   15
             /5    0

    -2   -1  +5    4
             -5   -6
             *5   -5
             /5    0

    *2    2  +5    7
             -5   -3
             *5   10
             /5    0

    /2    0  +5    5
             -5   -5
             *5    0
             /5    0
如你所见,如果X是-5,那么它可能是1-2*5或1/2-5。从-5开始反向工作:

-5 +5    0
   -5  -10
   *5  -25
   /5   -1
因此,如果我们从每一端开始,我们将位于中间列,唯一的公共值将是-1和0,这两条路径将进行8次计算,而不是16次只朝一个方向


这提出了一点,我没有注意到,整数除法不是1:1的映射,因此后退是不明确的-4/5->0,-3/5->0等直到4/5->0。0是最坏的情况,因为它是从0的任一侧接近的,但即使20/10到29/10都映射到相同的值2。这是一个相当大的障碍;当按被除数的大小后退时,它会增加可能的节点数,因此对于5,有3+5=8个可能的状态,而不是4个。

下面是一个递归解决方案的尝试(对于简单版本):

最终答案是:
∃ J∈ S(n)。x=[[j]]

也就是说,我们以增量方式构建所有可能的值(作为表达式),然后最终对所有值进行求值,以查看其中一个值是否可以生成
x
(也可以以增量方式进行求值)


但是,这里我假设在构建表达式时,线性使用
a
中的值。我意识到你的问题不是这样的…

是不是每个节点都有4条*(n-1)边?在这个图中,任何包含初始集所有元素的路径都成为一个表达式??每条边都是对表达式中前一个值的操作,因此对于表达式1*7+3,节点是1,7,21,带有边(*7)和(+3)。我没说清楚。因此,给定节点的4个传出边是下一个元素的4个可能操作,到达4个子节点。从7开始有+3、-3、*3和/3,到达节点10、4、21和2。在树的每一级,前面的路径无关紧要,因此您可以合并任何公共节点以减小正在进行的树的大小。当您使用下一个元素说
时,是否有(n-1)个下一个元素?因为任何元素都可以使用任何操作与任何其他元素组合。在你的例子中给定{1,7,3},从7开始,除了你已经提到的边之外,还有边+1,-1,*1,/1。我喜欢这种方法,它非常优雅,试图更好地理解它。干杯是的,我给出了一个单一路径中的节点示例,而不是整个树中的节点示例。我更新了答案,以便更清楚地显示示例树。我认为很明显,你实际上会想要比较你从两个方向得到的值,并且倾向于最匹配另一方的值;如果反向步进已达到某个较大的正数,则正向步进中较大的正节点最有可能产生解决方案。@AsiriRathnayake:我明白你的意思,这将使问题变得更加困难,因为在顺序不固定的情况下,存在置换数的解决方案。您可能需要为每个订单创建一个树。。。
Gen {'x'} = {'x'}
Gen {'x', 'y'} = {'x + y', 'x - y', 'y - x', 'x / y', 'y / x', 'x % y', 'y % x'}
S0 = {a[0]}
Gen S(i + 1) = {j ∈ S(i) | Gen {j, a[i + 1]}}