Is is possible to move from (a,b) to (c,d)

。_饼干妹妹 提交于 2020-01-05 04:21:06

问题


The problem was to output whether it is possible to move from a given point (a,b) to target (c,d)

We are restricted to positive co-ordinates only

The following two moves are possible

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

For instance, (1,1) to (5,4) is True You can do the following: Using 2nd move 3 times, (1,1) -> (1,2) -> (1,3) -> (1,4) Using 1st move 1 time (1,4) -> (5,4)

I came up with the following recursive method

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) Does my solution cover all the possible cases. I am unable to verify for sure since I do not have test cases, but I think I did take everything into account.

b) What is the time complexity of my solution? I think it is exponential but can't say for sure.

c) Is there a better solution to this (in terms of time complexity). Can we use dynamic programming?

Thank you for any input.


回答1:


If all the numbers have to be positive, then I believe there is a much quicker solution.

Trying to find if we can get from (a, b) to, say (14, 31), we can note that the only way with positive numbers to reach (14, 31) is to apply the second rule to (14, 17). The only way to get to (14, 17) is to apply the second rule to (14, 3). The only way to get to (14, 3) is to apply the first rule to (11, 3). The only way to (11, 3) is to apply the first rule to (8, 3), and so on. So the only values that can reach (14, 31) are

(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

So an algorithm is pretty simple. Loop on (c, d), replacing it with (c - d, d) if c > d and with (c, d - c) if c < d, stopping when you hit a match, when c == d, when c < a or d < b.

A variant of this described in a comment by Paul Hankin is O(log n), although I'm not going to try to prove it. This version is O(n), where n is the larger of c and d. Consecutive Fibonacci numbers will probably take the most steps.

Of course all this is meaningless if you can have negative numbers, since the first rule applied to (-17, 31) would also yield (14, 31) and you're back to exponential.




回答2:


Answers:

a. Yeah, it covers all cases.

b. It's complexity is exponential as from every state it tries to go to all the remaining states.

c. Yes, you can use dynamic programming by memoizing dp[a][b];

Initialie dp[][] all to -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

If you use dynamic programming complexity reduces to O(c*d)



来源:https://stackoverflow.com/questions/56597588/is-is-possible-to-move-from-a-b-to-c-d

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!