是否可以从(a,b)移至(c,d)

时间:2019-06-14 11:49:50

标签: algorithm recursion time-complexity dynamic-programming

问题是输出是否可以从给定点(a,b)移至目标(c,d)

我们仅限于正坐标

以下两个动作是可能的

(a,b) -> (a+b,b)
(a,b) -> (a,b+a)

例如,(1,1)(5,4)True 您可以执行以下操作:使用第二次移动3次,(1,1) -> (1,2) -> (1,3) -> (1,4)使用第一次移动1次(1,4) -> (5,4)

我想出了以下递归方法

def move(a,b,c,d):
    if a==c and b==d:
        return True
    elif a>c or b>d:
        return False
    else:
        ans = False
        if a < c:
            if move(a+b,b,c,d):
                return True
        if b < d:
            if move(a,b+a,c,d):
                return True
    return False

a)我的解决方案是否涵盖所有可能的情况?由于我没有测试用例,因此无法确定,但是我认为我确实考虑了所有问题。

b)我的解决方案的时间复杂度是多少?我认为它是指数的,但不能确定。

c)是否有更好的解决方案(在时间复杂度方面)。我们可以使用动态编程吗?

谢谢您的输入。

2 个答案:

答案 0 :(得分:6)

如果所有数字都必须为正,那么我相信有一个更快的解决方案。

尝试找出是否可以从(a, b)(14, 31),我们可以注意到,拥有正数才能达到(14, 31)的唯一方法是将第二条规则应用于{ {1}}。到达(14, 17)的唯一方法是将第二条规则应用于(14, 17)。到达(14, 3)的唯一方法是将第一个规则应用于(14, 3)(11, 3)的唯一方法是将第一个规则应用于(11, 3),依此类推。因此,唯一可以达到(8, 3)的值是

(14, 31)

因此,算法非常简单。在(14, 31) # Final (14, 17) # Rule 2 (14, 3) # Rule 2 (11, 3) # Rule 1 (8, 3) # Rule 1 (5, 3) # Rule 1 (2, 3) # Rule 1 (2, 1) # Rule 2 (1, 1) # Rule 1 上循环,如果(c, d)替换为(c - d, d),如果c > d则替换为(c, d - c),当您命中比赛时c < d停止, c == dc < a时。

Paul Hankin在评论中描述的一种变体是d < b,尽管我不会尝试证明这一点。此版本为O(log n),其中O(n)nc中的较大者。连续的斐波那契数字可能会采取最多的步骤。

当然,如果可以有负数,那么所有这些都是没有意义的,因为应用于d的第一个规则也会产生(-17, 31),并且您将返回指数级。

答案 1 :(得分:0)

答案:

a。是的,它涵盖了所有情况。

b。从每个状态到所有其他状态,它的复杂性都是指数级的。

c。是的,您可以通过记住dp [a] [b]使用动态编程。

初始 dp [] [] 全部为-1;

def move(a,b,c,d):
    // memoizing is here.
    if dp[a][b] != -1
        return dp[a][b];
    dp[a][b] = INF; // INF = 100000000;
    if a==c and b==d:
        return dp[a][b] = True
    elif a>c and b>d:
        return dp[a][b] = False
    else:
        ans = False
        if a < c:
            if move(a+b,b,c,d):
                return dp[a][b] = True
        if b < d:
            if move(a,b+a,c,d):
                return dp[a][b] = True
    return dp[a][b] = False

如果使用动态编程,则复杂度降低为O(c * d)