将一个点转换为另一个点的算法

时间:2015-09-05 08:42:07

标签: c++ algorithm math

您在(a,b)(c,d)表单中输入了四个整数作为输入。

如果您可以在操作(c,d)(a,b)之间进行选择,请确定是否可以从(a+b,b)获取(a,a+b)

所以,例如,(1,2) -> (3,2) -> (5,2) -> (5,7) -> (12,7) -> (12,19) -> ...

我尝试使用+ b x = c和 x + b = d来解决问题,但这不起作用。有什么想法吗?

3 个答案:

答案 0 :(得分:1)

可到达点的模式看起来并不简单。您可以将其视为具有合理斜率的斜线网络,从可到达的点开始。

以下是(1, 2)的模式。这些字母对应于连续的“世代”。

. . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . .
. A . B . C . D . E . F . G . H . I . J . K . L . M
. B . . C . . D . . E . . F . . G . . H . . I . . J
. C . . . D . . . E . . . F . . . G . . . H . . . I
. D . C . . E . D . . F . E . . G . F . . H . G . .
. E . . . . . F . . . . . G . . . . . H . . . . . I
. F . . D D . . G . . E E . . H . . F F . . I . . G
. G . D . . . . . H . E . . . . . I . F . . . . . J
. H . . . E . E . . I . . . F . F . . J . . . G . G
. I . . . . . E . . . J . . . . . F . . . K . . . .
. J . E E . F . . F . . K . F F . G . . G . . L . G
. K . . . E . . . . . . . L . . . F . . . . . . . M
. L . . . . . G E F F G . . M . . . . . H F G G H .
. M . F . F . . . . . . . . . N . G . G . . . . . .
. N . . F . . . H . . . . H . . O . . G . . . I . .
. O . . . . . F . . . G . G . . . P . . . . . G . .
. P . G . F G F . I . . . G . I . . Q . H . G H G .
. Q . . . . . . . . . F . F . . . . . R . . . . . .
. R . . G G . . . . J F F H . . H J . . S . . H H .
. S . H . . . H . G . . . . . . . . . . . T . I . .
. T . . . . . . F . . K . . . . H H . K . . U . . .
. U . . . G . . . G . . . . . I . . . I . . . V . .
. V . I H . H G I . G . L . G . . . G . . L . . W .
. W . . . H . G . . . H . . . . . . . . . . . . . X
. X . . . . . . . . . . . M G . G J G I . I J M . .

由于初看起来看起来不容易处理,因此可以通过(c, d)的回溯找到算法解决方案。

(a, b)= (1, 2)

def Backtrack(c, d):
    if c == a and d == b:
        print "Reachable !"
        return

    if d > 0 and c >= d:
        Backtrack(c - d, d)
    if c > 0 and d >= c:
        Backtrack(c, d - c)

Backtrack(9, 8)

Reachable !

除非导致快速终止的c == d,否则最多会进行一次递归调用,因此调用次数不会呈指数级增长。

答案 1 :(得分:1)

也许有一个优雅的数学解决方案,我不知道一个方程,但对我来说这看起来像一个搜索问题。我们有一个起点(a,b)和一个终点(c,d),在搜索的每个点我们都可以做两个动作:要么进入状态(a + b,b),要么(a,a + b)。一个简单的递归深度优先搜索可以做到。这里唯一棘手的问题是确定何时停止搜索。

让我们首先解决所有整数为正的情况。在这种情况下我们无法找到解决方案的限制条件很明显:当a超过c或b超过d时,我们不能希望在树的这个分支上找到更低的解决方案:

bool pathExistsForPositive(int a, int b, int c, int d) {
    if (a == c && b == d) return true; // success condition
    if (a > c || b > d) return false; // limiting condition
    return pathExistsForPositive(a+b, b, c, d)
        || pathExistsForPositive(a, a+b, c, d);
}

现在,对于数字不是正数的情况进行概括是比较棘手的,但是可行的。我希望这种直觉有​​所帮助。试着考虑在这种情况下何时必须停止搜索。

答案 2 :(得分:0)

您可以循环查找所有可能的解决方案

var sols = [[3,2]];

var sols2 = [];

for(depth=1;depth<5;++depth) {
    for(j=0;j<sols.length;++j) {
        var sol = sols[j];
        var sol1 = [sol[0]+sol[1],sol[1]];
        var sol2 = [sol[0],sol[0]+sol[1]];
        sols2.push(sol1,sol2);
        console.log(sol1);
        console.log(sol2);
    }
    sols = sols2;
    sols2 = [];
    console.log();
}

这只是找到了所有可能的解决方案。您可以优化代码以过滤掉所有失败的代码。

快速gcd检查将消除任何无效的输入。