问题是输出是否可以从给定点(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)是否有更好的解决方案(在时间复杂度方面)。我们可以使用动态编程吗?
谢谢您的输入。
答案 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 == d
或c < a
时。
Paul Hankin在评论中描述的一种变体是d < b
,尽管我不会尝试证明这一点。此版本为O(log n)
,其中O(n)
是n
和c
中的较大者。连续的斐波那契数字可能会采取最多的步骤。
当然,如果可以有负数,那么所有这些都是没有意义的,因为应用于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)