Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在无回溯的情况下查找从电路板一角到另一角的多条唯一路径_Python_Algorithm_Optimization - Fatal编程技术网

Python 在无回溯的情况下查找从电路板一角到另一角的多条唯一路径

Python 在无回溯的情况下查找从电路板一角到另一角的多条唯一路径,python,algorithm,optimization,Python,Algorithm,Optimization,我被一个算法优化所困扰 目标是找出在棋盘上从a点到B点可以使用多少种不同的方式,其中: A是左下角的正方形 B是右上角的正方形 每转一圈只能向上或向右转一次 下面是一个虚拟解决方案: # -*- conding: utf-8 -*- import time def solution(n, m, x, y): ret = 0 if x < n-1: ret += solution(n, m, x+1, y) if y < m-1: ret

我被一个算法优化所困扰

目标是找出在棋盘上从a点到B点可以使用多少种不同的方式,其中:

  • A是左下角的正方形
  • B是右上角的正方形
  • 每转一圈只能向上或向右转一次
下面是一个虚拟解决方案:

# -*- conding: utf-8 -*-
import time

def solution(n, m, x, y):
   ret = 0
   if x < n-1:
      ret += solution(n, m, x+1, y)
   if y < m-1:
      ret += solution(n, m, x, y+1)
   if x == n-1 and  y == m-1:
     ret = 1
   return ret

def wrapper(n, m):
    start = time.time()
    reponse = solution(n, m, 0, 0)
    stop = time.time()
    print "Response: %dx%d = %d\nTime : %f\n" % (n, m, reponse, stop-start)



if __name__ == "__main__":
    for i in range(10):
        wrapper(i+1,i+1)
    #wrapper(7,7)
    #wrapper(10,10)
    #wrapper(100,100)
    #wrapper(1000,1000)
    #wrapper(10000,10000) <- way too slow
#-*-条件:utf-8-*-
导入时间
def溶液(n、m、x、y):
ret=0
如果x#wrapper(1000010000)这样想:由于A点和B点位于同一位置,您必须移动相同数量的UPs和权限,但顺序将不同。因此,您需要找到不同组合的数量。

您不需要算法。只是数学。这里需要考虑的是:当你在右上方的方块上时,你没有任何不同的选择。让我们把它算作零。当你刚好在右上角的右边时,你唯一的选择就是向右走(一个选项),因为你不允许后退。当你刚好在右上角下方时,你唯一的选择就是往上走。让我们把它画出来

... 1 0
..... 1
从目标角向左/向下的角怎么办。从那里到拐角处有两条路(到邻居的各种选择的总和):你可以走到右边:

... 1 0
....2 1
扩展边我们总是使用“一”来扩展:一旦您位于顶部,只有一种方法可以到达右上角:

...1 1 1 0
...... 2 1
........ 1
........=1
但每个非边缘选择都是北部和东部邻国的数字总和:

...1 1 1 0
.....3 2 1
.......3 1
........ 1
等等。希望这能让你开始解决问题


对此也有不同的思考方式。给定一个NxN板,您必须进行2N次移动才能从一个角移动到另一个角。其中N个是北移,N个是东移。问题是:在一个2N长的字符串中,可以有多少不同的N个东移和N个北移组合。

您正在寻找帕斯卡三角形。甚至还提到了您的确切问题

动态规划:O(N) 它已经提到,问题有一个解决方案,使用a,以及它与的关系。另外,的条目为n×n的情况提供了一个很好的说明

n×n情形 通过使用上述资源,您可以得出结论,对于大小为n×n的网格,您需要计算C(2n-2,n-1)。通过将网格旋转45度并映射Pascal三角形,可以对其进行双重检查

实际上,直接计算这个数字需要以一种简单的方式计算最多3个不同的因子,这是一项非常昂贵的任务。如果你可以预先计算它们,那么这里就没有讨论,你可以说这个问题的复杂性是O(1)。如果你对预先计算的方法不感兴趣,那么你可以继续阅读

您可以使用动态规划(DP)计算这种不祥的数字。这里的诀窍是以较小的步骤执行该操作,这根本不需要计算大的阶乘数

也就是说,要计算C(n,k),你可以先把自己放在C(n,1)上,然后走到C(n,k)。让我们首先用C(n,k-1)来定义C(n,k)

基于此,您可以在Python中定义一个函数来计算C(n,k),如下所示:

def C(n, k):
    """
    Calculate C(n, k) using Dynamic Programming.
    C(n, k) = C(n, k - 1) * (n - k + 1) / k
    """
    C = 1
    for ki in range(1, k + 1):
        C = C * (n - ki + 1) / ki
    return C
它以线性时间O(N)运行

对于n×n的情况,需要计算C(2n-2,n-1)

n×m情形 对于一般的n×m情况,只需要计算C(n+m-2,m-1)

最后但并非最不重要

时间安排 我运行了以下网格大小的算法

      N x N      | Response's Length |   Time
-----------------+-------------------+-----------
      1 x 1      |           1 chars |  0.000001
     10 x 10     |           5 chars |  0.000004
    100 x 100    |          59 chars |  0.000068
   1000 x 1000   |         600 chars |  0.002207
  10000 x 10000  |        6018 chars |  0.163647
 100000 x 100000 |       60203 chars | 40.853971

由于涉及的数据量非常大,因此,在10万x 10万网格大小以上的操作成本似乎高得离谱。不过没什么好惊讶的。

作业?您尝试了什么?另外,请确保在记录时间之前,将计时代码的每个部分都运行一次。您需要让您的系统用该代码“预热”,否则您的第一次执行可能会有不正确的度量,而不是作业。我还尝试了一种非递归算法,该算法在第X步用所有可能的解填充数组,并在用B解填充数组时停止,但它消耗了太多的cpu和内存(即使它不会由于太多的递归而导致堆栈溢出)。难道没有O(1)解决方案吗?@BartlomiejLewandowski,不是。这里的阶乘是haskell的有效解决方案,但它会消耗大约15 Go的内存。
>> print "Response: %dx%d = %d" % (n, n, C(2 * n - 2, n - 1),)
Response: 10000x10000 = 5...
>> print "Response: %dx%d = %d" % (n, m, C(n + m - 2, m - 1),)
Response: 10000x10000 = 5...    
      N x N      | Response's Length |   Time
-----------------+-------------------+-----------
      1 x 1      |           1 chars |  0.000001
     10 x 10     |           5 chars |  0.000004
    100 x 100    |          59 chars |  0.000068
   1000 x 1000   |         600 chars |  0.002207
  10000 x 10000  |        6018 chars |  0.163647
 100000 x 100000 |       60203 chars | 40.853971