递归拼图

时间:2014-03-19 10:44:34

标签: algorithm recursion

最近,我的一位朋友向我提出要求解决这个问题的方法如下:

假设您有两个变量x和y。这些是唯一可用于程序存储的变量。有三种操作可以完成:

  • 操作1:x = x + y
  • 操作2:x = x-y
  • 操作3:y = x-y

现在,您将获得两个数字n1和n2以及目标数字k。从x = n1和y = n2开始,有没有办法使用上面提到的操作到达x = k?如果是,那么可以生成x = k的操作序列是什么。

示例:如果n1 = 16,n2 = 6且k = 28,则答案为是。顺序是:

Operation 1
Operation 1

如果n1 = 19,n2 = 7且k = 22,则答案为是。顺序是:

Operation 2
Operation 3
Operation 1
Operation 1

现在,我已经把问题包围了很长时间,但我没有得到任何初步的想法。我有一种感觉,这是递归,但我不知道边界条件应该是什么。如果有人可以指导我采用可以用来解决这个问题的方法,那将会非常有帮助。谢谢!

4 个答案:

答案 0 :(得分:4)

可能不是一个完整的答案,但是当且仅当kn1n2的最大公约数(GCD)的倍数时,才能证明序列存在。为简洁起见,我们写G = GCD(n1, n2)

首先,我将证明xy始终是G的整数倍。这种证明通过归纳非常简单。假设:x = p * Gy = q * G,对于某些整数pq

  • 最初,该假设符合G
  • 的定义
  • 每个规则都遵循归纳假设。规则产量:
    1. x + y = p * G + q * G = (p + q) * G
    2. x - y = p * G - q * G = (p - q) * G
    3. y - x = q * G - p * G = (q - p) * G

由于此结果,如果kkn1的GCD的整数倍,则n2只能有一个序列。

对于另一个方向,我们需要显示规则可以实现 G的任何整数倍。如果我们能够达到x = Gy = G,情况绝对如此。为此,我们使用Euclid's algorithm。考虑链接的wiki文章中的第二个实现:

function gcd(a, b)
    while a ≠ b
        if a > b
           a := a − b
        else
           b := b − a
    return a

这是规则2和3的重复应用,会产生x = Gy = G


知道存在解决方案,您可以应用BFS(如Amit's answer所示)来查找最短的序列。

答案 1 :(得分:1)

假设存在一个解决方案,可以使用BFS找到最短的序列来完成。

伪代码应该是这样的:

queue <- new empty queue
parent <- new map of type map:pair->pair
parent[(x,y)] = 'root' //special indicator to stop the search there
queue.enqueue(pair(x,y))
while !queue.empty():
   curr <- queue.dequeue()
   x <- curr.first
   y <- curr.second
   if x == target or y == target:
      printSolAccordingToMap(parent,(x,y))
      return
   x1 <- x+y
   x2 <- x-y
   y1 <- x-y
   if (x1,y) is not a key in parent:    
      parent[(x1,y)] = (x,y)
      queue.enqueue(pair(x1,y))
   //similarly to (x2,y) and (x,y1)

函数printSolAccordingToMap()只是追溯到地图上,直到找到根,然后打印出来。

请注意,此解决方案仅查找最佳序列(如果存在),但如果不存在则会导致无限循环,因此这只是部分答案。

答案 2 :(得分:0)

考虑到你同时拥有(x,y) always <= target & >0,如果没有,你可以通过简单的操作将它们带到范围内。如果您考虑这个约束,您可以创建一个图表,其中有O(target*target)个节点和边缘,您可以通过在该节点上的三个节点之间进行操作来查找。您现在需要评估从起始位置节点到目标节点(target,any)的最短路径。此处的假设是(x,y)值始终保持在(0,target)之内。使用djikstra时间复杂度为O(target*target*log(target))

答案 3 :(得分:0)

Vincent's answer中,我认为证据不完整。

让我们假设两个相对素数假设 n1 = 19 n2 = 13 GCD 1 。根据他的说法,如果 k GCD 的倍数,则序列退出。因为每个数字都是 1 的倍数。我认为每个 k 都不可能。

相关问题